ES6与React中this完全解惑
计划写很长的篇幅,预计12月初完成。
这篇文章涉及的知识较多,可能一次消化不了,可以渐渐来。
先说结论:
无论是ES6还是React的this,相对于ES5,只是增加了箭头函数this绑定了其封闭上下文,自己实现了该词法,其它的关于this的与ES5仍然一样。
目录:
1.ES5中对this使用的4种方式
2.ES6中箭头函数中的this
3.ES6中class中的this
4.React中组件里的this 组件里事件函数,其实相当于把对象方法赋值给新变量后再调用,这和ES5中是一样的,变成了函数调用,this指向全局。
要理解ES6的this知识,首先必须非常熟悉ES5里this的知识,要不然还是会一头雾水。
1.ES5中对this使用的4种方式
待补充
2.ES6中箭头函数中的this
先看几个例子
function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42
上面这个例子是阮一峰ES6入门里的一个例子,他在书中提到“箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象”,这种解释并不好,你也行还是不能真正理解上面这个例子。我更推荐MDN里对箭头函数this的说明“箭头功能不会创建自己的this;它使用封闭执行上下文的this值”。setTimeout里的函数的封闭上下文是foo函数,因此该箭头函数使用foo函数的this,在调用的时候,foo函数通过call将自己的id变成42,所以打印出的this.id是42。
下面的例子是MDN的例子,会从0每隔一秒打印递增的整数0,1,2,3... 。对照这个例子再体会MDN对于箭头函数的说明。
function Person(){ this.age = 0; setInterval(() => { console.log(this.age++) // 传递给setInterval的函数内的this与封闭函数中的this值相同 }, 1000); } var p = new Person();
还有一点,有些同学可能因为之前看了阮一峰对箭头函数this的解释“箭头函数体内的this对象,就是定义时所在的对象”,会产生疑惑,它每次使用的是这个对象的起初的深拷贝的副本还是引用值,通俗的问就是,当执行上下文的this值上的属性变化了,箭头函数里的this上的属性是否变化呢。答案是也跟着变化,我们根据MDN的解释,它使用封闭执行上下文的this值。上面的例子其实已经可以验证这个问题了,为了更清楚一下,我们稍微改一下。
function Person(){ this.age = 0; setInterval(() => { console.log(this.age++); }, 1000); } var p = new Person(); p.age = 50;
我们在控制台可以看到,从50每隔1秒递增打印一个整数。
由于 this 已经在词法层面完成了绑定,通过 call() 或 apply() 方法调用一个箭头函数时,只是传入了参数而已,对 this 并没有什么影响:
var adder = { base : 1, add : function(a) { var f = v => v + this.base; return f(a); }, addThruCall: function(a) { // console.log(this.base) var f = v => v + this.base; var b = { base : 2 }; return f.call(b, a); } }; console.log(adder.add(1)); // 输出 2 console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3)
注意与一开始的例子区别,一开始的例子是对箭头函数外层函数使用call,而这个例子是直接对箭头函数使用call。addThruCall内的this与ES5一样,是调用对象的this,里面的箭头函数同样使用这个this。我们在后面加两句
var cc = adder.addThruCall; console.log(cc(1))
控制台输出NaN,想想是不是和ES5对象方法调用一样的呢。
参考链接:1.MDN箭头函数