我對this的理解(JavaScript)

注意: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的指向 不得不說callapplybind三個函數

這三個方法能夠解決如上【隱式丟失】的問題。

new綁定

使用new來調用函數,或者說發生構造函數調用,則會自執行以下操做:

  1. 建立一個全新的對象
  2. 這個新對象會被執行[[原型]]鏈接
  3. 這個新對象會綁定到函數調用的this
  4. 若是函數沒有返回其餘對象,則會默認返回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
複製代碼

不管如何,foothis被設置爲他被建立時的環境(在上面的例子中,就是全局對象)。這一樣適用於在其餘函數內建立的箭頭函數:這些箭頭函數的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

相關文章
相關標籤/搜索