本文参考以下文章:
1、深入理解ES6箭头函数的this以及各类this面试题总结
阅读本文请先阅读以上文章
要点总结:
导致不同的最本质原因是:函数表达式中有自己的this对象,而箭头函数中无自己的this对象。
函数表达式中的this:
1、this总是代表它的直接调用者, 也就是说是动态绑定的。例如 obj.func ,那么func中的this就是obj
2、在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window (约定俗成)
3、在严格模式下,没有直接调用者的函数中的this是 undefined
4、使用call,apply,bind(ES5新增)绑定的,this指的是绑定的对象
5、匿名函数,定时器中的函数,由于没有默认的宿主对象,所以默认this指向window
箭头函数中的this:
箭头函数中因为没有自己的this对象,所以在箭头函数中引用this时,会根据作用域链的寻找机制,去它的父执行上下文(注意:简单对象(非函数)是没有执行上下文的!这是作用域链的相关知识)里寻找this。
注意事项:
在需要动态上下文的场景中使用箭头函数你要格外的小心,这些场景包括:定义对象方法、定义原型方法、定义构造函数(why?this对象指向window对象了,相当于定义了全局变量)、定义事件回调函数。
经典例题:
window.val = 1;
var obj = {
val: 2,
dbl: function () {
this.val *= 2;
val *= 2;
console.log(val);
console.log(this.val);
}
};
// 说出下面的输出结果
obj.dbl();//12行
var func = obj.dbl;
func();//14行
解析:
结果是: 2 4 8 8
12行代码调用,val变量没有指定对象前缀,默认从函数中找,找不到则从window中找全局变量,(涉及到作用域链的寻找机制:为什么不是找到obj对象中的val属性?因为按照作用域链机制,会先在自己的执行上下文中找,这个执行上下文指的是定义的dbl这个函数,如果找不到会到它的父执行上下文中找,这个父执行上下文就到了最顶层,即window对象。重中之重知识点:简单对象(非函数)是没有执行上下文的!)即 val *=2 就是 window.val *= 2,this.val默认指的是 obj.val ;因为 dbl()第一次被obj直接调用;
14行代码调用,func() 没有任何前缀,类似于全局函数,即 window.func调用,所以第二次调用的时候, this指的是window, val指的是window.val,第二次的结果受第一次的影响。