JavaScript 學習筆記 之 THIS (二) - 綁定規則

 

綁定規則

this的綁定規則有四種 

  1. 默認綁定 (全局對象或者undefined(嚴格模式下))
  2. 隱式綁定(調用時函數上下文對象,obj.fun())
  3. 顯式綁定(call , apply , bind(硬綁定))
  4. new綁定(新建的對象會被綁定到構造函數中的this上)

詳細介紹

1 . 默認綁定

調用沒有任何修飾函數時引用默認綁定,this指向全局對象

但是如果定義時使用嚴格模式(use strict),則不能將全局對象用於默認綁定,因此this會綁定到undefined,而在嚴格模式下調用卻不影響

2.隱式綁定

調用位置的上下文對象決定,調用函數中的this會指向最後一層調用對象

		function foo() {
			console.log(this.name);
		}
		var obj = {
			name: "obj",
			foo: foo
		}
		obj.foo();//obj

但是隱式綁定存在着一個隱患(隱式丟失)

		var name = "global";
		var bar = obj.foo;
		bar();//global

雖然bar是obj.foo的一個引用,但是實際上引用的是foo函數本身,此時bar()實際上是變成foo(),應用了默認綁定

另一種隱式丟失的情況出現在參數傳遞中

		function doFoo(fn) {
			fn();
		}

		doFoo(obj.foo) //global

因爲參數傳遞時也會發生隱式賦值 fn = obj.foo

3.顯式綁定

function.call(...)

function.apply(...)

這兩個函數區別在於第二部分的參數,具體可以看我之前的博客,現在先不討論這個問題

這兩個函數的作用都是將第一個參數綁定到function中的this上,如果第一個參數是個原始值(String Boolean 或者Number),這個原始值會轉換成對象形式(new String(..)等),這通常被稱爲裝箱

		function foo() {
			console.log(this.name);
		}
		var obj = {
			name: "obj",
			foo: foo
		}
		
		foo.call(obj);//obj

然而顯式綁定依然存在着我們之前提出的丟失綁定的問題

但是顯式綁定的的一個變種可以解決這個問題(硬綁定)

		function foo() {
			console.log(this.name);
		}
		var obj = {
			name: "obj",
			foo: foo
		}

		var bar = function() {
			foo.call(obj);
		}
		bar(); //obj

這種方式其實就是ES5中的bind()方法

bind方法與call方法的參數形式是一樣的,不同之處在於bind只是返回一個硬綁定了this對象的函數,而call則是綁定了函數中的this對象後執行函數(即使調用call函數的函數本身返回自己,this綁定的對象依然會丟失)

4.new綁定

最後一條this的綁定規則與構造函數有關

JavaScript中的構造函數實際上只是一個使用了new操作符的普通函數

JavaScript實際上不存在所謂的"構造函數",存在的只有對函數的"構造調用"

當函數在new表達式中被調用時,它會初始化新創建的對象

發生的步驟如下

  1. 創建(構造)一個全新的對象
  2. 這個新對象會被執行[[Prototype]]連接(不是本篇討論的問題,暫時可以忽略)
  3. 這個新對象會被綁定到函數調用的this.

  4. 如果函數沒有返回其他對象,則new表達式會自動返回這個新對象
		function foo(a) {
			this.a = a;
		}

		var bar = new foo(2);
		console.log(bar.a);//2

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章