话不多说,直接先来看几个函数调用的场景
functionfoo(){console.log(this.a);};leta=1;foo();constobj={a:2,foo:foo};obj.foo();constc=newfoo();
接下来一个个分析上面的场景
对于直接调用foo来说,不管foo函数被放在了什么地方,this 一定是指向 window
对于obj.foo()来说,只需记住,谁调用了函数,谁就是this,所以在这个场景下foo函数中的this就是obj对象
对于new来说,this被永远绑定在了c上面,不会被任何方式改变this
再来看看箭头函数中的this
functiona(){return()=>{return()=>{console.log(this);};};};console.log(a()()());
首先箭头函数其实是没有this的,箭头函数中的this只取决于包裹箭头函数的第一个普通函数的this。在上面这个例子中,因为包裹箭头函数的第一个普通函数就是a,所以此时的this是window。另外对箭头函数使用bind这类函数是无效。
最后情况也就是bind这些改变上下文API了,对于这些函数来说,this取决于第一个参数,如果第一个参数为空,那么就是window。
如果对一个函数进行多次bind的情况下
leta={};letfn=function(){console.log(this)};fn.bind().bind(a)()//=>打印出什么?
其实可以把上诉代码转换成另一种形式
letfn2=functionfn1(){returnfunction(){returnfn.apply()}.apply(a)};fn2();
可以从上诉代码中发现,不管我们给函数bind几次,fn中的this永远由第一次bind决定,所以结果永远是window。
leta={name:'xyz'};functionfoo(){console.log(this.name);};foo.bind(a)();//=>'xyz'
当多个规则同时出现的情况,这时候不同的规则之间会根据优先级最高的来决定this最终指向哪里。
首先,new方式优先级别最高,接下来是bind这些函数,然后是obj.foo()这种调用方式,最后是foo这种调用方式,同时,箭头函数的this一旦被绑定,就不会再被任何方式改变。
最后是关于this指向的流程图,帮助梳理思路(只针对于单个规则)
---END---