JavaScript 有一套完全不同于其它語言的對 this 的處理機制。
在五種不同的情況下 ,this 指向的各不相同。
this;
當在全部范圍內(nèi)使用 this,它將會指向全局對象。
譯者注:瀏覽器中運行的 JavaScript 腳本,這個全局對象是
window。
foo();
這里 this 也會指向全局對象。
ES5 注意: 在嚴格模式下(strict mode),不存在全局變量。 這種情況下
this將會是undefined。
test.foo();
這個例子中,this 指向 test 對象。
new foo();
如果函數(shù)傾向于和 new 關(guān)鍵詞一塊使用,則我們稱這個函數(shù)是 構(gòu)造函數(shù)。
在函數(shù)內(nèi)部,this 指向新創(chuàng)建的對象。
function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // 數(shù)組將會被擴展,如下所示
foo.call(bar, 1, 2, 3); // 傳遞到foo的參數(shù)是:a = 1, b = 2, c = 3
當使用 Function.prototype 上的 call 或者 apply 方法時,函數(shù)內(nèi)的 this 將會被
顯式設(shè)置為函數(shù)調(diào)用的第一個參數(shù)。
因此函數(shù)調(diào)用的規(guī)則在上例中已經(jīng)不適用了,在foo 函數(shù)內(nèi) this 被設(shè)置成了 bar。
注意: 在對象的字面聲明語法中,
this不能用來指向?qū)ο蟊旧怼?因此var obj = {me: this}中的me不會指向obj,因為this只可能出現(xiàn)在上述的五種情況中。 譯者注:這個例子中,如果是在瀏覽器中運行,obj.me等于window對象。
盡管大部分的情況都說的過去,不過第一個規(guī)則(譯者注:這里指的應(yīng)該是第二個規(guī)則,也就是直接調(diào)用函數(shù)時,this 指向全局對象)
被認為是JavaScript語言另一個錯誤設(shè)計的地方,因為它從來就沒有實際的用途。
Foo.method = function() {
function test() {
// this 將會被設(shè)置為全局對象(譯者注:瀏覽器環(huán)境中也就是 window 對象)
}
test();
}
一個常見的誤解是 test 中的 this 將會指向 Foo 對象,實際上不是這樣子的。
為了在 test 中獲取對 Foo 對象的引用,我們需要在 method 函數(shù)內(nèi)部創(chuàng)建一個局部變量指向 Foo 對象。
Foo.method = function() {
var that = this;
function test() {
// 使用 that 來指向 Foo 對象
}
test();
}
that 只是我們隨意起的名字,不過這個名字被廣泛的用來指向外部的 this 對象。
在 閉包 一節(jié),我們可以看到 that 可以作為參數(shù)傳遞。
另一個看起來奇怪的地方是函數(shù)別名,也就是將一個方法賦值給一個變量。
var test = someObject.methodTest;
test();
上例中,test 就像一個普通的函數(shù)被調(diào)用;因此,函數(shù)內(nèi)的 this 將不再被指向到 someObject 對象。
雖然 this 的晚綁定特性似乎并不友好,但這確實是基于原型繼承賴以生存的土壤。
function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
當 method 被調(diào)用時,this 將會指向 Bar 的實例對象。