注意:
this
是在函數被調用的時候發生的綁定,它指向什麼徹底取決於在哪裏被調用。javascript
在嚴格和非嚴格模式下,this
的指向有所不一樣java
function f1() {
return this;
}
// In a browser:
f1() === window; // true
// In Node:
f1() === global; // true
//嚴格模式以下:
function f2() {
'use strict'; // see strict mode
return this;
}
f2() === undefined; // true
複製代碼
那麼在函數在執行過程當中調用位置如何決定this的綁定對象? 有四條規則app
就是,經常使用的函數調用。函數
如上f一、f2
函數的調用,都採用【默認綁定】。綁定到全局對象window
或者global
上。oop
就是,對象的方法調用。若是說函數的調用位置有上下文對象,或者說被某個對象擁有或者包 含,那就是隱式綁定。ui
function foo() {
console.log( this.a );//this指向obj對象
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
var obj1 =
複製代碼
當含有this
的方法賦值給變量,而後被調用時,會發生隱式丟失,即丟失了綁定的對象。 例如:this
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函數別名!
var a = "oops, global"; // a 是全局對象的屬性
bar(); // "oops, global"
複製代碼
foo
函數隱式綁定了obj
對象,在賦值給變量bar
後,被調用打印this.a
結果是全局變量a
的值。 隱式綁定丟失所綁定的對象後,採用默認的綁定方式,this
執行全局環境spa
當含有this
的方法應用於回調函數時,也會發生隱式丟失。 沒錯,這種狀況一樣也發生在回調函數,類比「賦值給變量」。.net
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
var a = "oops, global"; // a 是全局對象的屬性
setTimeout( obj.foo, 100 );//oops,global
複製代碼
那麼,上述遇到的隱式丟失該如何解決呢?這就須要說到下一個規則【顯示綁定】code
能夠在某個對象上強制調用函數。或者說改變this的指向 不得不說call
、apply
、bind
三個函數
這三個方法能夠解決如上【隱式丟失】的問題。
使用new
來調用函數,或者說發生構造函數調用,則會自執行以下操做:
[[原型]]
鏈接this
上this
,也就是這個新對象。注意,第4點。默認返回this
,也就是說能夠返回其餘對象。好比:
function Man(name) {
console.log('man', this);
this.name = name;
return {}; //函數有本身的返回對象
}
function Woman(name) {
console.log('woman:', this);
this.name = name;
}
var man = new Man('Davin');
console.log(man) // {}
var woman = new Woman('Lisa');
console.log(woman) //{name: "Lisa"}
複製代碼
在箭頭函數中,this
與封閉詞法環境的this
保持一致。在全局代碼中,它將被設置爲全局對象。
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
複製代碼
不管如何,foo
的 this
被設置爲他被建立時的環境(在上面的例子中,就是全局對象)。這一樣適用於在其餘函數內建立的箭頭函數:這些箭頭函數的this
被設置爲封閉的詞法環境
的。以下:
// 做爲對象的一個方法調用
var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true
// 嘗試使用call來設定this
console.log(foo.call(obj) === globalObject); // true
// 嘗試使用bind來設定this
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
複製代碼
箭頭函數中this的指向並未發生變化。
參考閱讀 《你不知道的JavaScript(上)》 MDN 之 this 透徹理解並掌握JavaScript的this