javascript this繫結機制
阿新 • • 發佈:2018-11-25
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指向。後續會詳細探討,敬請期待............