简单谈谈javascript中this的隐式绑定
我们先来看一个例子
functionfoo(){ console.log(this.a); } varobj={ a:2, foo:foo }; obj.foo();//2
this指向了obj,因为foo执行时的call-site(可以理解为调用时所在作用域)在obj上面。注意是运行的时候,和在哪里声明的没有关系。
call-siteandcall-stack
call-site姑且理解为调用域,call-stack为调用栈。如下代码可以辅助我们理解
functionbaz(){ //call-stackis:`baz` //so,ourcall-siteisintheglobalscope console.log("baz"); bar();//<--call-sitefor`bar` }
在baz()中调用bar(),所以bar的调用域是baz,此时bar的调用栈只有baz;而baz本身暴露在全局作用域中,所以它的调用域则也在全局作用域中。
functionbar(){ //call-stackis:`baz`->`bar` //so,ourcall-siteisin`baz` console.log("bar"); foo();//<--call-sitefor`foo` } functionfoo(){ //call-stackis:`baz`->`bar`->`foo` //so,ourcall-siteisin`bar` console.log("foo"); } baz();//<--call-sitefor`baz`
理解之后再回头看开头的例子,是不是感觉清晰了很多。其实this只是指向了它的call-site
还有如下玩法:
functionfoo(){ console.log(this.a); } varobj2={ a:42, foo:foo }; varobj1={ a:2, obj2:obj2 }; obj1.obj2.foo();//42 ImplicitlyLost(隐式丢失) functionfoo(){ console.log(this.a); } varobj={ a:2, foo:foo }; varbar=obj.foo;//functionreference/alias! vara="oops,global";//`a`alsopropertyonglobalobject bar();//"oops,global"
虽然bar引用了obj上的foo,但实际上相当于是直接对foo引用而已,所以会默认绑定到全局。
functionfoo(){ console.log(this.a); } functiondoFoo(fn){ //`fn`isjustanotherreferenceto`foo` fn();//<--call-site! } varobj={ a:2, foo:foo }; vara="oops,global";//`a`alsopropertyonglobalobject doFoo(obj.foo);//"oops,global"