歡迎您光臨本站 註冊首頁

js this 繫結機制深入詳解

←手機掃碼閱讀     niceskyabc @ 2020-05-03 , reply:0

本文例項講述了js this 繫結機制。分享給大家供大家參考,具體如下:
函式呼叫位置
與詞法作用域相反的是,this的指向由函式執行時決定,它是動態的,隨著函式呼叫位置變化而變化。
要理解 this,首先要理解呼叫位置:呼叫位置就是函式在程式碼中被呼叫的位置(而不是宣告的位置)。只有仔細分析呼叫位置才能回答這個問題:這個this到底引用的是什麼?
function baz() { // 當前呼叫棧是:baz // 因此,當前呼叫位置是全域性作用域 console.log( "baz" ); bar(); // <-- function="" baz="" -=""> bar // 因此,當前呼叫位置在baz中 console.log( "bar" ); foo(); // <-- function="" baz="" -=""> bar -> foo // 因此,當前呼叫位置在bar中 console.log( "foo" ); } baz(); // <-- baz的呼叫位置
多數現代桌面瀏覽器都內建了開發者工具,其中包含JavaScript偵錯程式。你可以在工具中給函式的第一行程式碼設定一個斷點,或者直接在第一行程式碼之前插入一條 debugger;語句。執行程式碼時,偵錯程式會在那個位置暫停,同時會展示當前位置的函式呼叫列表,這就是你的呼叫棧。因此,如果你想要分析this的繫結,使用開發者工具得到呼叫棧,然後找到棧中第二個元素,這就是真正的呼叫位置。
this 繫結規則
函式的呼叫位置決定了this的繫結物件,當我們找到呼叫位置後,然後判斷需要應用下面四條規則中的哪一條。
獨立函式呼叫
獨立函式呼叫,this 指向函式呼叫位置所在的包含環境物件。
function foo() { console.log( this.a ); } var a = 2; foo(); // 2
作為物件的方法呼叫
當函式作為某個物件的方法被呼叫時,this 指向這個物件。
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo(); // 2
特別注意:雖然函式foo並不屬於obj物件,但呼叫位置使用obj的上下文來呼叫函式。我一直在強調呼叫位置的重要性,因為你可能一不留神就會忽略掉它,看下面的列子:
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; // 函式別名! 步驟1 var a = "oops, global"; // a是全域性物件的屬性 bar(); // "oops, global" 步驟2
在步驟1中,變數bar是obj.foo 的一個引用,它實際指向的是函式foo。所以使用bar()與直接使用foo()並沒有不同。
使用 .call/ .apply 繫結
每建立一個函式,這個函式就有了兩個繼承而來的方法:call和apply。
它們的第一個引數是一個物件,它們會把這個物件繫結到this,接著在呼叫函式時指定這個 this 。因為你可以直接指定 this 的繫結物件,因此我們稱之為顯式繫結。
function foo() { console.log( this.a ); } var obj = { a:2 }; foo.call( obj ); // 2
new繫結
使用 new 來呼叫函式,或者說發生建構函式呼叫時,會自動執行下面的操作。
建立(或者說構造)一個全新的物件。 這個新物件會被執行[[原型]]連線,即指向建構函式的原型Foo.prototype。 這個新物件會繫結到函式呼叫的 this 。 如果函式沒有返回其他物件,那麼 new 表示式中的函式呼叫會自動返回這個新物件。
function foo(a) { this.a = a; } var bar = new foo(2); console.log( bar.a ); // 2
使用 new 來呼叫 foo(..) 時,我們會構造一個新物件並把它繫結到 foo(..) 呼叫中的 this 上。
優先順序
如果要判斷一個執行中函式的this繫結,就需要找到這個函式的直接呼叫位置。找到之後就可以順序應用下面這四條規則來判斷 this 的繫結物件。
由 new 呼叫?繫結到新建立的物件。 由 call 或者 apply (或者 bind )呼叫?繫結到指定的物件。 由上下文物件呼叫?繫結到那個上下文物件。 預設:在嚴格模式下繫結到 undefined ,否則繫結到全域性物件。
一定要注意,有些呼叫可能在無意中使用預設繫結規則。如果想「更安全」地忽略 this 繫結,你可以使用一個DMZ物件,比如 ø = Object.create(null) ,以保護全域性物件。


[niceskyabc ] js this 繫結機制深入詳解已經有200次圍觀

http://coctec.com/docs/javascript/show-post-232589.html