每個函數的this是在調用時被綁定的,完全取決於函數調用的位置!!!!
1.this的綁定規則
(1)默認綁定
function foo(){
console.log( this.a );
}
var a = 2;
foo();
函數沒有任何修飾進行調用的,所以在默認情況下會直接將this綁定到全局空間。但這只是在非嚴格模式下是這樣的,嚴格模式下,this將會是undefined
(2) 隱式綁定
function foo() {
console.log(this.a);
}
var obj = {
a: 42,
foo: foo
};
obj.foo();
此時,obj爲this的執行上下文,this指向object
隱式丟失
function foo() {
console.log(this.a);
}
function doFoo(fn) {
fn();
}
var obj = {
a: 2,
foo: foo
};
var a = "oops,global";
doFoo(obj.foo);
foo在doFoo中調用,按照前面的規則,fn()是真正調用foo()的地方,this應該指向doFoo,但是!!!輸出結果確實全局變量a,"oops,global"
(3)顯示綁定
call與apply
function foo() {
console.log(this.a);
}
var obj = {
a:2
};
foo.call(obj);
這時,this被強制綁定到obj上 ,而且這種綁定一旦綁定就不能修改,es5提供了內置方法Function.prototype.bind,用法如下:
function foo(something) {
console.log(this.a,something);
return this.a + something;
}
var obj = {
a:2
};
var bar = foo.bind(obj);
var b = bar(3);
console.log(b);
bind將this綁定到obj對象,3傳給了something,返回的結果是5
(4) new綁定
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log(bar.a);
在foo直接爲this賦值
2.綁定的優先級
new綁定 > 顯式綁定 > 隱式綁定 > 默認綁定
3.一些例外
(1)將null,undefined作爲this的綁定對象傳入call,apply或者bind會被忽略,實際應用的是默認綁定規則。
但如果把this賦值爲null,可能會導致全局變量被修改,因此我們應該採取更加安全的做法,創建一個空對象來代替null
function foo(a,b){
console.log("a:" + a + ",b:" + b);
}
var k = Object.create(null);
foo.apply(k,[2,3]);
var bar = foo.bind(k,2);
bar(3);
(2)間接引用
function foo() {
console.log(this.a);
}
var a = 2;
var o = {a : 3, foo: foo};
var p ={ a: 4};
o.foo();
(p.foo=o.foo)();