function foo() {
console.log(this);
console.log(this.a);
}
function doFoo(fn) {
fn();
}
var obj = {
a: 2,
foo: foo
}
var a = 'oops,global';
doFoo(obj.foo);
预处理后的执行环境栈
ECStack={
globalContext:{
VO:{
foo:<reference to function foo(){}>,
doFoo:<reference to function doFoo(){}>,
obj:undefined,
a:undefined
}
}
}
调用doFoo函数后的执行环境栈
ECStack={
globalContext:{
VO:{
foo:<reference to function foo(){}>,
doFoo:<reference to function doFoo(){}>,
obj:undefined,
a:undefined
}
},
<doFoo>functionContext:{
AO:{
arguments:{
0:<reference to function foo(){}>,
length:1,
callee:doFoo
},
this:Object window,
fn:<reference to function foo(){}>
}
}
}
调用fn函数后的执行环境栈
ECStack = {
globalContext: {
VO: {
foo: < reference to
function foo() {} > ,
doFoo: < reference to
function doFoo() {} > ,
obj: undefined,
a: undefined
}
},
< foo > functionContext: {
AO: {
arguments: {
length: 0,
callee: foo
},
this: window
}
}
}
函数foo被调用时,函数doFoo的执行环境被摧毁,当前环境栈只有全局执行环境和foo函数执行环境。函数foo明面上是通过函数doFoo的AO来调用的,但是在调用的同时,调用对象被摧毁,foo的this指向window对象。(因为无法解释所以强行解释)
判断this依据它的调用方式判断。
- foo();//指向window对象
- obj.foo();//指向obj对象
- obj1.obj2.foo();//指向obj2对象
- setTimeout(obj.foo,100);//指向window对象
- 这个函数相当于
function setTimeout(fn,delay){fn()}
,也就是将函数指针赋值给另一个函数的形参,调用时指向window对象
- 这个函数相当于
- call,apply,bind强行绑定:call是通过参数一个一个传入。apply是通过数组传入参数。bind返回一个强行绑定this值的函数,该函数无论通过什么样的方式进行调用都不会再修改this的值。