首頁 >web前端 >js教程 >JavaScript進階系列—this 的工作原理

JavaScript進階系列—this 的工作原理

黄舟
黄舟原創
2017-02-08 09:48:401539瀏覽
  • 全域範圍內

  • 函數呼叫

  • 方法呼叫

  • 呼叫

  • 方法的賦值表達式

  • JavaScript 有一套完全不同於其它語言的對 this 的處理機制。 在五種不同的情況下,this 指向的各不相同。

  • 全域範圍內
  • this;

    當在全部範圍內使用 this ,它將會指向全域物件。

  • 函數呼叫
foo();

這裡 this 也會指向全域物件。

方法呼叫

test.foo();

這個範例中, this 指向 test 物件。

呼叫建構子

new foo();

如果函數傾向於和 new 關鍵字一塊使用,則我們稱這個函數為 建構子。 在函數內部,this 指向新建立的物件。

明確的設定 this

function foo(a, b, c) {}

var bar = {};
foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示
foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3

當使用 Function.prototype 上的 call 或 apply 方法時,函數內的 this 將會被明確地設定為函數呼叫的第一個參數。

因此函數呼叫的規則在上例中已經不適用了,在 foo 函數內 this 被設定為bar了。

常見誤解

儘管大部分的情況都說的過去,不過第一個規則(譯者註:這裡指的應該是第二個規則,也就是直接調用全局函數時,this 指向全局物件) 被認為是JavaScript語言另一個錯誤設計的地方,因為它從來就沒有實際的用途。

Foo.method = function() {
    function test() {
        // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象)
    }
    test();
}

一個常見的誤解是 test 中的 this 將會指向 Foo 對象,實際上不是這樣子的。

為了在 test 中取得 Foo 物件的引用,我們需要在 method 函數內部建立一個局部變數指向 Foo 物件。

Foo.method = function() {
    var that = this;
    function test() {
        // 使用 that 来指向 Foo 对象
    }
    test();
}

that 只是我們隨意取的名字,不過這個名字被廣泛的用來指向外在的 this 對象。 在 閉包 一節,我們可以看到 that 可以作為參數傳遞。

注意: 在物件的字面宣告語法中,this 不能用來指向物件本身。 因此 var obj = {me: this} 中的 me 不會指向obj,因為 this 只可能出現在上述的五種情況中。 譯者註:這個例子中,如果是在瀏覽器中執行,obj.me 等於window 物件。

方法的賦值表達式

另一個看起來奇怪的地方是函數別名,也就是將一個方法賦值給一個變數。

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 被呼叫時,this 將會指向 Bar 的實例物件。

以上就是JavaScript進階系列—this 的工作原理的內容,更多相關內容請關注PHP中文網(www.php.cn)!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn