super-fool / blog

珍藏经典, 分享思想, 共同进步.加油
3 stars 0 forks source link

箭头函数到底存在的意义在哪里?( ) => {/*do nothing...*/} #13

Open super-fool opened 5 years ago

super-fool commented 5 years ago

缺点:

  1. 没有constructor.
  2. 无法new: 因为它没有构造函数.
  3. 没有prototype: 因为无法new.
  4. 没有arguments
  5. 无法使用call | apply | bind去改变this上下文.
  6. 无法使用generator | yield.
super-fool commented 5 years ago

this

箭头函数的this指向包含其的函数(父函数)的上下文.

var b ='window';
var a = {
    b: 'object-a',
    c: function(){
        return () => console.log(this.b);
    },
    d: () => console.log(this.b),
    f: function(){
        return this.d;
    },
    h: function(){
        return this.d.bind(this);
    }
}
a.c()(); // window
a.f()(); // object-a
a.h(); // window

上面的栗子看出了, 箭头函数的this不会在执行时去判断其父函数是谁, 而是会在编译的时候去判断其父函数. 所以a.f()的箭头函数不会认为f是箭头函数的父函数.

super-fool commented 5 years ago

优点

function Count() {
    this.num = 1;
    this.time = setInterval(function(){
        console.log(this.num++);
        setTimeout(function(){
            clearInterval(this.time);
        },4000)
    },1000)
}
var count = new Count();
count.time;

我们发现会无限 output: NaN(typeof NaN eq 'number'). 这个原因是因为我们需要去绑定 定时器中callback的上下文,不然上下文会指向window


我们可以使用箭头函数来解决:

function Count() {
    this.num = 1;
    this.time = setInterval(() => {
        console.log(this.num++);
        setTimeout(() => {
            clearInterval(this.time);
        },4000)
    },1000)
}
var count = new Count();
count.time;

其实, 我们还可以在函数内的this先赋值给一个对象:

function Count() {
    var _self = this;
    this.num = 1;
    this.time = setInterval(() => {
        console.log(_self.num++);
        setTimeout(() => {
            clearInterval(_self.time);
        },4000)
    },1000)
}
var count = new Count();
count.time;
super-fool commented 5 years ago

箭头函数的this指向的是上下文的this,在编译的时候就已将确定了,但是我们还是可以使用call, bind, apply 来改变this:

let hyk = {name: 'huyakun'};

function sayName () {
  console.log(this.name);
  return () => {
    console.log(this.name);
  }
}

sayName.call(hyk)(); // 输出 huyakun
super-fool commented 5 years ago

使用剩余运算符来代替arguments的缺失:

var arrowFn = (...args) => { console.log(args) };
arrowFn(1, 2, 3); // [1, 2, 3]
super-fool commented 3 years ago

箭头函数还有个牛逼之处:

let num = 0;
const test = () => ((num = 12), num)

const ret = test(); // => 12

普通函数时, 我们必须要用{}来包裹函数体.

写一个获取URL parameters 的 方法

const getURLParameters = (url: string) => {
  return (url.match(/([^?=&]+)(=([^&]+))/g) || []).reduce(
    (a, v) => (
      (a[v.slice(0, v.indexOf["="])] = v.slice(v.indexOf("=") + 1)), a
    ),
    {}
  );
};

getURLParameters("google.com"); // {}
getURLParameters("http://url.com/page?name=Adam&surname=Smith");
// {name: 'Adam', surname: 'Smith'}