翻譯自文章The Simple Rules to ‘this’ in Javascript。
肯定什麼是 this
並不是難事。總的來說,經由過程查找函數被挪用時的位置(和要領)就能夠決議。遵照以下劃定規矩,按優先級分列。
劃定規矩
經由過程
new
關鍵字挪用組織函數,函數內的this
是一個全新的對象。function ConstructorExample() { console.log(this); this.value = 10; console.log(this); } new ConstructorExample(); // -> {} // -> { value: 10 }
經由過程
apply
、call
或bind
挪用一個函數,函數內的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 }
假如一個函數作為對象的要領挪用,即運用
.
標記挪用該函數,this
是挪用該函數的對象。換句話說,當.
處於被挪用函數的左側,則this
就是左側的對象。var obj = { value: 5, printThis: function() { console.log(this); } }; obj.printThis(); // -> { value: 5, printThis: ƒ }
假如函數作為一般函數挪用,意味着挪用體式格局不相符以上恣意一種,
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
- 假如相符上述多個劃定規矩,則越前面的劃定規矩會決議
this
的值。 假如函數是一個
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()
時,我們沒有運用 new
、 bind/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
語法。
該文章首發於我的個人站點