全域作用域下
this;
當在全域作用域中使用 this,它指向全域物件。
這裡詳細介紹下全局物件:
全域物件(Global object) 是在進入任何執行上下文之前就已經建立了的物件;
這個物件只存在一份,它的屬性在程式中任何地方都可以訪問,全域物件的生命週期終止於程式退出那一刻。
全域物件初始建立階段將 Math、String、Date、parseInt 作為自身屬性,等屬性初始化,同樣也可以有額外建立的其它物件作為屬性(其可以指向到全域物件本身)。例如,在 DOM 中,全域物件的 window 屬性就可以引用全域物件本身。
所以在 console 內輸入 window 和 this.window 是一樣的。
呼叫一個函數時
foo();
在這裡,this 同樣指向全域物件。
呼叫一個方法時
test.foo();
在這個例子中,this 將會指向 test 物件。
呼叫一個建構子時
new foo();
一個函數在被呼叫時和關鍵字 new 一起使用,我們稱之為建構子。此時在函數內,this 指向新建的物件。
明確設定時
function foo(a, b, c) {}// var bar = {}; foo.apply(bar, [1, 2, 3]); // array will expand to the below foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
當使用 Function.prototype 的 apply 和 call 方法時,this 的值為明確設定為此方法的第一個參數。
因此,不同於呼叫一個函數時的規則,上例中 this 指向了 bar。
這裡介紹下 call 和 apply 方法:
call 方法:
語法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定義:呼叫一個物件的一個方法,以另一個物件取代當前物件。
apply 方法:
語法:apply([thisObj[,argArray]])
定義:應用某一物件的一個方法,用另一個物件取代目前物件。
這裡我們要注意一點,在物件的字面聲明時,this 不能用來指向物件本身。如下:
var obj = {me: this}
這裡,this 不會指向 obj,this 的應用只限於以上五種情形。
總結
儘管上述情形在大多數時候是有意義的,但是第二種情形(即調用一個函數時)的 this 實際上是很少有用途的,這被認為是 Javascript 設計上的另一個錯誤。
Foo.method = function() { function test() { // this is set to the global object } test(); }
根據我們上面所述,這裡的 this 將會指向全域對象,而不是 Foo 函數。
為了在 test 中獲得指向 Foo 的途徑,我們需要在 method 內部建立一個局部變數指向 Foo。
Foo.method = function() { var that = this; function test() { // Use that instead of this here } test(); }
that 只是普通的變數名,但它常被用來指向外在的 this。
還有一個比較有趣的地方與函數別名相關,即將一個方法賦值給一個變數時。
var test = someObject.methodTest; test();
上例中,test 將會被當做一個普通函數看待,所以根據第二種情況(即調用一個函數時),其內部的 this 將會指向全域變量,而不是 someObject。
儘管,this 晚綁定初看起來是個不好的決定,但實際上這是原型式繼承工作的基礎。
function Foo() {} Foo.prototype.method = function() {}; function Bar() {} Bar.prototype = Foo.prototype; new Bar().method();
此時,當 method 被呼叫時,它將指向 Bar 的實例物件。