# this 指向某個建構子 (constructor) 所建立的物件。但事實上在 JavaScript 裡面, this 所代表的不僅僅是那個被建立的物件。 預設綁定會在callback的this指定給Global Object (Window 物件) > 透過 addEventListener 註冊了 click 事件,事件中的 this 指的是「觸發事件的元素」。 > 要是我們在事件的 callback function 加入 ajax 的請求,那麼根據前面所說的,預設綁定 (Default Binding) 會把這個 callback function 的 this 指定給 global object,也就是 window。 ```javascript= el.addEventListener("click", function(event) { // 透過 that 參考 var that = this; console.log( this.textContent ); $ajax('[URL]', function(res) { // this.textContent => undefined console.log(that.textContent, res); }); }, false); ``` 像這樣,我們將事件內的 this 先用一個叫 that 的變數儲存它的參考,那麼在 ajax 的 callback function 就可以透過 that 來存取到原本事件中的 this 了。 ### 強制指定 this 的方式 #### bind(),call(),apply() `bind():` ```javascript= el.addEventListener("click", function(event) { console.log( this.textContent ); // 透過 .bind(this) 來強制指定該 scope 的 this $ajax('[URL]', function(res) { console.log(this.textContent, res); }.bind(this)); }, false); ``` * bind()讓這個function在呼叫前先綁定某個物件,使他不管怎麼被呼叫都能有固定的this。 * 尤其常用像是在callback function這種類型的場景,看想像是先綁定好this,然後讓function在需要時被呼叫的類型。 * .call() 與 .apply()依造呼叫時的需要帶入不同的物件作為該function的this。 * 使用在context較常變動的場景。 ```javascript= var list = [1, 5, 8]; function add() { return Array.from(arguments).reduce(function(sum, num) { return sum + num; }); } console.log(add.call(null, 1, 2));// 3 console.log(add.apply(null, list));// 14 ``` ### this 與前後文本 (context) 綁定的基本原則 #### 預設綁定 (Default Binding) 宣告在全域範疇 (global scope) 的變數,與同名的全域物件 (window 或 global) 的屬性是一樣的意思。 因為預設綁定的關係,當 function 是在普通、未經修飾的情況下被呼叫,也就是當 function 被呼叫的當下如果沒有值或是在 func.call(null) 或 func.call(undefined) 此類的情況下,此時裡面的 this 會自動指定至全域物件。 但若是加上 "use strict" 宣告成嚴格模式後,原本預設將 this 綁定至全域物件的行爲,會轉變成 undefined。 #### 隱含式綁定 (Implicit Binding) 指的是,即使 function 被宣告的地方是在 global scope 中,只要它成為某個物件的參考屬性 (reference property),在那個 function 被呼叫的當下,該 function 即被那個物件所包含。 ```javascript= function func() { console.log( this.a ); } var obj = { a: 2, foo: func }; func(); // undefined obj.foo(); // 2 ``` ```javascript= function func() { console.log( this.a ); } var obj = { a: 2, foo: func }; obj.foo(); // 2 var func2 = obj.foo; func2(); // undefined ``` :::warning **決定 this 的關鍵不在於它屬於哪個物件,而是在於 function「呼叫的時機點」** ::: 這個 function 的呼叫,是透過 new 進行的嗎? 如果是,那 this 就是被建構出來的物件。 這個 function 是以 .call() 或 .apply() 的方式呼叫的嗎? 或是 function 透過 .bind() 指定? 如果是,那 this 就是被指定的物件。 這個 function 被呼叫時,是否存在於某個物件? 如果是,那 this 就是那個物件。 如果沒有滿足以上條件,則此 function 裡的 this 就一定是全域物件,在嚴格模式下則是 undefined。 [重新認識 JavaScript: Day 20 What's "THIS" in JavaScript (鐵人精華版)](https://ithelp.ithome.com.tw/articles/10193193) [談談 JavaScript 中的 "this" 和它的問題](https://pjchender.blogspot.com/2016/03/javascriptthisbug.html)