2019-03-11/ES6之箭头函数与this

ES6中新引入了箭头函数,引入箭头函数有两个方面的作用:更简短的函数并且不绑定this。现在分别看下两个作用:

更简短的函数表达:

(参数1, 参数2, …, 参数N) => { 函数声明 }

//相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
(参数1, 参数2, …, 参数N) => 表达式(单一)

// 当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}

// 没有参数的函数应该写成一对圆括号。
() => {函数声明}

不绑定this

在箭头函数出现之前,每个新定义的函数都有它自己的this:
1.构造函数=> this是新对象的实例/严格模式下为undefined
2.函数作为对象的方法调用=>this指向该对象
3.全局环境下定义的函数=>this指向window

function Person() {
  // Person() 构造函数定义 `this`指向它的实例.
  this.age = 0;

  setInterval(function growUp() {
    // 在非严格模式, growUp()函数定义 `this`指向全局对象window, 
    // 与在 Person()构造函数中定义的 `this`并不相同.
    this.age++;
  }, 1000);
}

var p = new Person();

现在我们来解决上述this不一致的问题:
方案一
在ECMAScript 3/5中,将this值分配给封闭的变量。

function Person() {
  // Person() 构造函数定义 `this`指向它的实例.
  var _this=this;
// 将Person的实例this保存到封闭的变量_this中
_this.age=0

  setInterval(function growUp() {
    _this.age++;
  }, 1000);
}

var p = new Person();

方案二
创建[bind绑定函数],以便将预先分配的this值传递到绑定的目标函数(上述示例中的growUp()函数)。

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。因此,在下面的代码中,传递给setInterval的函数内的this与封闭函数中的this值相同:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| 正确地指向 p 实例
  }, 1000);
}

var p = new Person();

当然,箭头函数也有其不适用的场景:
场景1
第一个场合是定义函数的方法,且该方法内部包括this。

const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

上面代码中,cat.jumps()方法是一个箭头函数,这是错误的。调用cat.jumps()时,如果是普通函数,该方法内部的this指向cat;如果写成上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。

场景2
第二个场合是需要动态this的时候,也不应使用箭头函数。

var button = document.getElementById('press');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});

上面代码运行时,点击按钮会报错,因为button的监听函数是一个箭头函数,导致里面的this就是全局对象。如果改成普通函数,this就会动态指向被点击的按钮对象。

你可能感兴趣的:(2019-03-11/ES6之箭头函数与this)