js中this物件的理解
最近在參加的幾場面試中都涉及到了對於js
中this
物件的理解,那麼怎樣去理解this
呢?這裡針對不同的場景通過程式碼來幫助我們理解好this
。
this到底指向什麼?
this
指向什麼呢?一言以蔽之:
this最終指向的是那個呼叫它的物件
下面通過程式碼來分析this
的指向問題。
預設繫結全域性變數window
var a = 'hello';
function foo() {
console.log( this.a );
}
foo(); // hello
這裡呼叫foo()
就相當於window.foo()
。因此this
引用的是window
。也就是下面這句話:
如果一個函式中有
this
,但是它沒有被上一級的物件所呼叫,那麼this
指向的就是window
隱式繫結
function foo() {
console.log( this.a );
}
var obj = {
a: 'hello',
foo: foo
};
obj.foo(); // hello
這裡呼叫foo
的是obj
,因此this
指向的是obj
物件。
再來看一個例子:
function foo() {
console.log( this.a );
}
var obj2 = {
a: 'hello',
foo: foo
};
var obj1 = {
a: 'world',
obj2: obj2
};
obj1.obj2.foo(); // hello
這個例子可能看起來比較暈,那麼this
指向的是obj1
還是obj2
呢?其實關於this
的引用還有一句話要記住:
如果一個函式中有
this
,這個函式中包含多個物件,儘管這個函式是被最外層的物件所呼叫,this
指向的也只是它上一級的物件
理解了上面兩個例子之後再看一種情況:
function foo() {
console.log( this.a );
}
var obj = {
a: 'hello',
foo: foo
};
var bar = obj.foo; // 函式引用傳遞
var a = "Global";
bar(); // "Global"
這裡this
指向的是window
物件,想要理解這點還需要記住一句話:
this
永遠指向的是最後呼叫它的物件,也就是看它執行的時候是誰呼叫的
上面的例子中雖然函式foo
是被物件obj
所引用,但是在將foo
賦值給變數bar
的時候並沒有執行,最終foo
是由bar
來執行的,而bar
指向的是window
物件。
顯示繫結
通過bind(),apply(),call()函式可以顯示的繫結this作用域,它接收的第一個引數即是上下文物件並將其賦給this。
function foo() {
console.log( this.a );
}
var obj = {
a: 'hello'
};
foo.call(obj); // hello
如果我們傳遞第一個值為簡單值,那麼後臺會自動轉換為對應的封裝物件。如果傳遞為null
,那麼結果就是在繫結預設全域性變數。看下面的例子:
function foo() {
console.log( this.a );
}
var obj = {
a: 2
};
var a = 'hello';
foo.call( null); // hello
new新物件繫結
如果是一個建構函式,那麼用new
來呼叫,那麼繫結的將是新建立的物件。如:
function foo(a) {
this.a = a;
}
var bar = new foo('hello');
console.log(bar.a);// hello
this在閉包裡的簡單應用
如果已經理解了上面this
的基本用法,那麼我們來看一個this
在閉包的指向問題:
var flag = "window";
var object = {
flag : "local",
sayFlag: function(){
//返回一個匿名函式
return function(){
console.log(this.flag);
}
}
}
object.sayFlag()(); //window
這裡的this
是在一個匿名函式裡面呼叫的,object.sayFlag()
函式返回的是一個匿名函式,也就是說this
應該指向的是匿名函式的執行環境,那麼匿名函式的執行環境到底應該是什麼呢?
匿名函式的執行環境具有全域性性,
this
通常指向window
那麼如何訪問“local呢”?
var flag = "window";
var object = {
flag : "local",
sayFlag: function(){
var that = this; //此處的this是object的引用
//返回一個匿名函式
return function(){
alert(that.flag);
}
}
}
object.sayFlag()(); //local