1. 程式人生 > >javascript this繫結機制

javascript this繫結機制

1.查詢呼叫點:函式被呼叫的位置

大多數瀏覽器(Google)都內建開發者工具,其中就包含JS偵錯程式。為什麼要找函式的呼叫點?因為函式在呼叫點的呼叫形式決定了this繫結。

	function foo(something) {
            //debugger;
			console.log(this.a,something);
			return this.a + something;
		}

		var obj = {
			a: 2
		};

		var bar = function () {
			return foo.apply(obj,arguments);
		};

		var b = bar(3);

2. this繫結規則

預設繫結:獨立函式呼叫,即函式被一個直白的,毫無修飾的函式引用呼叫,例如foo(), foo的this關鍵字被繫結到window。

隱含繫結:物件方法呼叫,即函式被作為物件的一個方法呼叫,在呼叫點,函式必須是物件obj的一個成員方法;例如obj.foo( ), foo的this關鍵字被繫結到obj。

顯式繫結:呼叫函式的call(),apply()方法,顯示的傳遞thisArgs,例如foo.call(obj), foo的this關鍵字被繫結到obj, 與隱含繫結的區別是,顯示繫結的環境物件obj可以不包含這個函式foo,即兩者無任何關係,只是執行時obj作為環境物件傳遞給函式foo使用。

構造繫結:使用new關鍵字呼叫函式,函式的this關鍵字被繫結到當前構造的例項。

3. 硬繫結

硬繫結是顯示繫結的變種,當一個物件的方法作為引數傳遞給另一個函式時,隱含的繫結會丟失,當然函式執行時的this繫結取決於函式被呼叫的形式,我們不知道這個回撥函式foo在另一個函式內部setTimeout中是如何呼叫的(最終的呼叫形式),為了防止不確定的事情發生,我們完全可以將回調函式包裝成一個硬繫結函式後再傳到給setTimeout。如下圖:

   	function foo(){
    		console.log(this.a);
    	}
    	
    	var obj = {
    		a: 2
    	}
		
		/*
    	將foo包裝成bar函式,無論如何呼叫和回撥,都只能改包裝函式bar的this繫結,內層函式foo的繫結始終不變,
    	所以我們稱之為硬繫結,即明確又堅定。
    	*/
    	var bar = function() {
    		//顯示繫結
    		foo.call(obj);
    	}

    	//傳遞包裝函式bar
    	setTimeout(bar,100);

    	//使用函式表示式包裝bar函式
    	setTimeout( function () { foo.call(obj)},100)

4. 箭頭函式

ES6新增了箭頭函式,箭頭函式不僅僅是函式表示式的簡寫,省去了枯燥無味的function關鍵字,它的this繫結機制不屬於以上的任何一種,它實際上採用的是詞法作用域規則,箭頭函式的this關鍵字繼承外層詞法作用域的this指向。後續會詳細探討,敬請期待............