[譯]淺顯易懂的 this 取值劃定規矩

翻譯自文章The Simple Rules to ‘this’ in Javascript

肯定什麼是 this 並不是難事。總的來說,經由過程查找函數被挪用時的位置(和要領)就能夠決議。遵照以下劃定規矩,按優先級分列。

劃定規矩

  1. 經由過程 new 關鍵字挪用組織函數,函數內的 this 是一個全新的對象。

    function ConstructorExample() {
        console.log(this);
        this.value = 10;
        console.log(this);
    }
    new ConstructorExample();
    // -> {}
    // -> { value: 10 }
  2. 經由過程 applycallbind 挪用一個函數,函數內的 this 就是傳入的參數。

    function fn() {
        console.log(this);
    }
    var obj = {
        value: 5
    };
    var boundFn = fn.bind(obj);
    boundFn();     // -> { value: 5 }
    fn.call(obj);  // -> { value: 5 }
    fn.apply(obj); // -> { value: 5 }
  3. 假如一個函數作為對象的要領挪用,即運用 . 標記挪用該函數, this 是挪用該函數的對象。換句話說,當 . 處於被挪用函數的左側,則 this 就是左側的對象。

    var obj = {
        value: 5,
        printThis: function() {
            console.log(this);
        }
    };
    obj.printThis(); // -> { value: 5, printThis: ƒ }
  4. 假如函數作為一般函數挪用,意味着挪用體式格局不相符以上恣意一種, this 就是全局對象。在瀏覽器中就是 window

    function fn() {
        console.log(this);
    }
    // If called in browser:
    fn(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

    *這個劃定規矩能夠類比於劃定規矩3——差別之處在於這個函數自動掛載到了 window 對象上,所以能夠這麼明白,當我們挪用 fn() 時實在挪用的事 window.fn() ,所以 this 就是 window

    console.log(fn === window.fn); // -> true
  5. 假如相符上述多個劃定規矩,則越前面的劃定規矩會決議 this 的值。
  6. 假如函數是一個 ES2015 箭頭函數,會疏忽上述一切劃定規矩, this 設置為它被建立時的上下文。為了找到 this 的值,須要找到函數被建立時的環境中 this 的值。

    const obj = {
        value: 'abc',
        createArrowFn: function() {
            return () => console.log(this);
        }
    };
    const arrowFn = obj.createArrowFn();
    arrowFn(); // -> { value: 'abc', createArrowFn: ƒ }

    我們返回去看劃定規矩3,當我們挪用 obj.createArrowFn() 時, createArrowFn 中的 this 就是 obj 對象,我們用 . 標記挪用。假如我們在全局中建立一個箭頭函數, this 就是 window

運用劃定規矩

下面在幾個例子中運用一下我們的劃定規矩。試一下經由過程兩種差別的體式格局挪用函數時 this 的值。

找到運用的劃定規矩

var obj = {
    value: 'hi',
    printThis: function() {
        console.log(this);
    }
};
var print = obj.printThis;
obj.printThis(); // -> {value: "hi", printThis: ƒ}
print(); // -> Window {stop: ƒ, open: ƒ, alert: ƒ, ...}

obj.printThis() 很顯然運用的是劃定規矩3——運用 . 標記。 print() 運用了劃定規矩4,在挪用 print() 時,我們沒有運用 newbind/call/apply. 標記,所以這裏的 this 是全局對象 window

多重劃定規矩運用

如上文提到,當運用多個劃定規矩時,優先運用前面的劃定規矩。

var obj1 = {
    value: 'hi',
    print: function() {
        console.log(this);
    },
};
var obj2 = { value: 17 };

假如劃定規矩2和3同時運用,劃定規矩2優先。

obj1.print.call(obj2); // -> { value: 17 }

假如劃定規矩1和3同時運用,劃定規矩1優先。

new obj1.print(); // -> {}

關於東西庫

一些 JavaScript 庫有時候會在函數中主動綁定它以為最有效的內容到 this 上。比如在 JQuery中,在觸發事宜時 DOM 元素被綁定到了 this 上。在運用東西庫時發明取值不相符上述劃定規矩時,請檢察庫文檔。很可能運用了 bind 語法。

該文章首發於我的個人站點

    原文作者:BingqiChen
    原文地址: https://segmentfault.com/a/1190000014463944
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞