js 的 this 绑定问题,让多数新手懵逼,部分老手觉得恶心,这是因为this的绑定 ‘难以捉摸’,出错的时候还往往不知道为什么,相当反逻辑。
让我们记住这五点:
1.预编译过程:this=>window
2.全局作用域里面:this=>window
3.call/apply可以改变this指向,指向的是第一个参数;
4.this始终指向其最后的直接调用者;
5.箭头函数的this只受其外层作用域影响,也指向外层作用域的this;
理解的深刻些,来看看下面几个例子吧
再来一个典型例子,那么大家应该就掌握了this的大部分问题了
第一处打印调用fun(),这里其实就是把a.say这个函数的函数体赋给了fun这个函数,相当于在全局空间下写了一个func函数,但是这个时候没谁调用,所以此时的this指向window,因此打印222。
第二处应该都知道答案,打印调用了a.say(),按照我们前面说的谁调用函数,函数里面的this就指向谁,因此这里的this指向a,所以打印111。
第三处比较复杂,它调用了b.say(a.say))。这里其实是吧a.say这个函数体替换了原本b中fun的地方,我们在调用b.say()这个方法的时候,里面的this是指向b的,但是这个this并不在fun里面而是在say里面,稍微整理就是
看到了吧,所以还是没谁调用这个fun(),那就指向window,也就打出222;
所以fun里面的this和我们所想的指向b的那个this不是一个东西,fun里面的this是在预编译阶段的指向window的,因此这里也打印222。其实和第一种直接在全局调用a.say的函数体方法差不多。
第四个b.say = a.say; b.say();其实也第二种一模一样的意思,障眼法而已,不过此时的this指向b而已,因此打印333。
最后让我们看看箭头函数的this,
const obj = {
a: () => { console.log(this) }
}
obj.a() //打出来的是window
在使用箭头函数的例子里,因为箭头函数默认不会使用自己的this,而是会和外层的this保持一致,最外层的this就是window对象。
再看看call与箭头函数一起的时候;
const obj = {
a: () => { console.log(this) }
}
obj.a.call('123') //打出来的结果依然是window对象
因为上文我们说到window.setTimeout()中函数里的this默认是window,我们也可以通过箭头函数使它的this和外层的this保持一致