ES6之箭头函数中的this
在讲箭头函数中的this之前我们先介绍一下普通函数中的this。
普通函数中的this:
(1)this指向它的直接调用者
(2)默认的,非严格模式下,没找到直接调用者则指向window
(3)严格模式下,没直接调用者的this是undefined
(4)使用call,apply,bind绑定对象,则this指向被绑定的对象。
ES5中 window.val = 1; var obj = { val: 2, dbl: function () { this.val *= 2; val *= 2; console.log(val); console.log(this.val); } }; obj.dbl(); var func = obj.dbl; func(); // 输出结果 2 4 8 8
分析:(1) 12行代码调用
val变量在没有指定对象前缀,默认从函数中找,找不到则从window中找全局变量
即 val *=2 就是 window.val *= 2
this.val默认指的是 obj.val ;因为 dbl()第一次被obj直接调用
(2)14行代码调用
func() 没有任何前缀,类似于全局函数,即 window.func调用,所以
第二次调用的时候, this指的是window, val指的是window.val。第二次的结果受第一次的影响。
作用域链
当在函数中使用一个变量的时候,首先在本函数内部查找该变量,如果找不到则找其父级函数,最后直到window,全局变量默认挂载在window对象下。
箭头函数中的this
箭头函数中的this特性
(1)箭头函数中的this对象就是定义时所在的对象,而不是使用时所在的对象
(2)不可以使用new命令创建实例
(3)不可以使用argument对象,该对象在函数体内不存在。如果要用,可以用reset参数代替
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。
(5)由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。
示例:
var obj = { say: function () { setTimeout(() => { console.log(this) }); } } obj.say();
输出:
obj
此时的 this指的是定义它的对象, obj,而不是 window。
多层嵌套的箭头函数:
var obj = { say: function () { var f1 = () => { console.log(this); // obj setTimeout(() => { console.log(this); // obj }) } f1(); } } undefined obj.say()
输出:
Object
Object
由于fa定义时所处的函数中的this是指向obj的,所以无论嵌套多少层都指向obj。
箭头函数与函数比较:
function Timer() { this.s1 = 0; this.s2 = 0; // 箭头函数 setInterval(() => this.s1++, 1000); // 普通函数 setInterval(function () { this.s2++; }, 1000); } var timer = new Timer(); setTimeout(() => console.log('s1: ', timer.s1), 3100); setTimeout(() => console.log('s2: ', timer.s2), 3100);
输出:
s1: 3 s2: 0
Timer函数内设置了2个定时器,第一个是箭头函数,其this是指向定义它的函数Timer,所以调用timer.s1会被更细3次。第二个是普通函数,其this是指向运行时所在函数的作用域。
普通函数和箭头函数混杂嵌套:
var obj = { say: function () { var f1 = function () { console.log(this); // window, f1调用时,没有宿主对象,默认是window setTimeout(() => { console.log(this); // window }) }; f1(); } } obj.say()
输出
Window
Window
因为 箭头函数所在的函数位置为f1,f1中的this是指向window,所以箭头函数的this与指向window。
箭头函数中使用call()、apply()、bind():
(function() { return [ (() => this.x).bind({ x: 'inner' })() ]; }).call({ x: 'outer' });
输出:
["outer"]
由于箭头函数没有自己的this,所以使用bind()方法无法改变this的指向。
总结:箭头函数中的this指向是固定的,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数内部没有this,导致内部的this就是外层代码块的this。正因为它没有this,所以也就不能用作构造函数。