简单谈谈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"