关于ES6中箭头函数的this问题

什么是箭头函数

用法

ES6 容许使用“箭头”(=>)定义函数javascript

<p id="test1">测试</p>

  var p1 = document.getElementById('test1');
  p1.addEventListener('click', () => {
        p1.style.color = "red";
     }, false);

在es5中至关于java

var p1 = document.getElementById('test1');
   p1.addEventListener('click', function () {
             //直接经过dom的方法改变颜色
             this.style.color = "red"; 
      },false);

可是咱们思考一个问题——当咱们把第一段代码中的p1换成this时
this会指向哪里app

p1.addEventListener('click', () => {
         
      this.style.color = "red";//   'color' is not undefined
     }, false);

这时咱们就会想this为何没有做用,而在es5中this是指向了p1dom

箭头函数有个使用注意点。

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
this对象的指向是可变的,可是在箭头函数中,它是固定的。函数

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到100毫秒后。若是是普通函数,执行时this应该指向全局对象window,这时应该输出21。可是,箭头函数致使this老是指向函数定义生效时所在的对象(本例是{id: 42}),因此输出的是42学习

箭头函数的this

this指向的固定化,并非由于箭头函数内部有绑定this的机制,实际缘由是箭头函数根本没有本身的this,致使内部的this就是外层代码块的this。正是由于它没有this,因此也就不能用做构造函数测试

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

上面代码中,转换后的es5清楚地说明了,箭头函数里面根本没有本身的this,而是引用外层的this。this

因为箭头函数没有本身的this,因此固然也就不能用call()、apply()、bind()这些方法去改变this的指向。es5

(function() {
  return [
    (() => this.x).bind({ x: 'inner' })()
  ];
}).call({ x: 'outer' });
// ['outer']

一样的因为箭头函数没有本身的this 因此bind传统的显性绑定无效 内部的this指向外部this
在javascript的学习中, this的指向问题一直是个难点,特别是在对象方法中使用this时,必须更加当心。由此箭头函数在很大程度上减小了咱们的困扰。code

箭头函数this词法

话又说回来,当咱们使用箭头函数时不使用常规的四种this绑定,又该怎么决定this的指向问题呢?
箭头函数是根据外层(函数或者全局)做用域来决定this

让咱们看看箭头函数的此法做用域:

function foo() {
            //返回箭头函数
            return(a) => {
                //this 继承自foo()
                console.log(this.a);
            };
        }
        var obj1 = {
            a:2
        };
        var obj2 ={
            a:3
        };
        var bar = foo.call(obj1);
        bar.call(obj2); //是2, 不是3!!!

foo()内部建立的箭头函数会捕获调用时foo()的this。因为foo()的this绑定到了obj1,因此bar(引用箭头函数)的this也会绑定到obj1,上文说过箭头函数this对象的指向是固定的因此后面的call修改不了绑定,即便是new也不行。

箭头函数能够像bind()同样确保函数的this被绑定到指定对象上,此外, 其重要性还体如今它更常见的词法做用域取代了传统的this的机制。实际上, 在ES6以前咱们就已经在使用一种集合和箭头函数彻底同样的模式了。

function foo() {
            var self = this;
            setTimeout(function() {
                console.log(self.a)
            },100)
        }
        var obj = {
            a:2
        };
        foo.call(obj);

和箭头函数同样self = this 看起来均可以取代bind(), 可是从本质上来看,它们是想代替this这个机制。

注意

若是常常编写this风格的代码,又喜欢用箭头函数或者self= this的方法来否认this机制。
那么或许你应当:

  1. 只使用词法做用域并彻底摒弃错误的this风格
  2. 彻底采用this风格,在必要时仍使用bind(), 避免使用箭头函数或者self = this。
相关文章
相关标签/搜索