JavaScript中的this到底指向谁?
书中介绍了四种规则来判断,如下,优先级从高到低。
1.(new绑定)函数是否在new中调用?如果是的话,this绑定的是新创建的对象。
function foo(a){
this.a = a;
}
var bar = new foo(2);
console.log(bar.a); // 2
2.(显示绑定)函数是否通过call、apply调用?如果是的话,this绑定指定的对象上。
function foo(){
console.log(this.a);
}
var obj={
a:2
}
foo.call(obj); // 2
3.(隐形绑定)函数是否在某个上下文对象中调用?如果是的话,this绑定的是那个上下文对象。
function foo(){
console.log(this.a);
}
var obj={
a:2,
foo:foo
}
obj.foo(); // 2
上述代码中,foo函数在obj中被调用,所以这里this指向obj。
function foo(){
console.log(this.a);
}
var obj2={
a:2,
foo:foo
}
var obj1={
a:1,
obj2:obj2
}
obj1.obj2.foo(); // 2
上述代码中,foo函数在obj2中被调用,所以this指向obj2。
function foo(){
console.log(this.a);
}
var obj={
a:2,
foo:foo
}
var bar=obj.foo;
var a="global"
bar(); // "global"
这三段代码很相似,区别在于第三个多了一个 var bar=obj.foo; ,foo是个函数(引用类型),所以bar引用的是foo函数本身,所以这段代码相当于:
function foo(){
console.log(this.a);
}
var obj={
a:2,
foo:foo
}
var a="global"
foo(); // "global"
这时,this指向的是window对象(全局对象),相当于下面的第四条规则。在javascript中总是说等于号“=”是赋值运算符,其实这种说法不太全面,我觉得对“=”的理解应该为:赋值或引用。看下面代码:
var a=1;
var b=a; // 赋值
var c={username:123};
var d=c; // 引用
b=2;
d.username=456;
console.log(a); // 1
console.log(c.username); // 456
因为变量a是个值类型,存储在内存的栈中,所以对b进行修改不会影响到a的原本值;而c是个对象(引用类型),存放在内存的堆中,变量c和d指向同一个内存地址,对d进行修改会影响到c。
4.(默认绑定)如果函数不在严格模式下,this绑定的是全局对象。
function foo(){
console.log(this.a);
}
var a=2;
foo(); // 2
其实,第3条和第4条的this指向都和函数被调用的位置有关,可以合为一条规则,即:this指向函数被调用位置所在的作用域的对应对象,在某个函数内部被调用,那么this就指向这个函数对象,在全局作用域中被调用,那么this就指向全局对象。
所以,对于this的指向,我们可以总结为:在通常情况下(没有new和显示绑定),this指向函数被调用位置所在的作用域的对应对象。