JavaScript #10 — This (下)
接續之前的 This (上),再來繼續未完成的部份。
「new」關鍵字綁定
在函式前 宣告 new
關鍵字時這就是 建構子。
function GetNum(number) {
this.number = number
}let obj = new GetNum(777)obj.number //777
如以上的範例,透過 new
關鍵字宣告建構一個新的物件,並將它傳入 obj
變數中, 透過傳入的引數 777 ,在建立物件的當下,會將 參數 number
綁定obj
物件中的 this.number
,這就是 透過 new
關鍵字來綁定 this
的方式。
整理 new
關鍵字 流程 :
- 透過
new
關鍵字宣告建構一個新的物件。 - 將物件中
.__proto__
屬性指向.prototype
並形成 原型鏈 (Prototype Chain)。 this
會指向新的物件。- 透過
new
關鍵字宣告建構式會自動回傳內容(除非以 return 方式回傳其它 物件)。
結論整理
綁定 this 有以下四種,如下 :
- 「new」關鍵字綁定
- 顯式綁定 (Explicit Binding)
- 隱含式綁定 (Implicit Binding)
- 預設綁定 (Default Binding)
綁定的例外
DOM 的監聽事件
在 DOM element 的監聽事件中 this
會指向觸發節點元素。
/*HTML*/
<button class="btn">我要學會 HTML!</button>/*JavaScript*/
let btn = document.querySelector('.btn')btn.addEventListener('click', function () {
console.log('click', this)
})
就如上範例所說的,監聽事件中 this
會指向觸發節點元素。如果在監聽事件中加入了 callback function ,就如之前 預設綁定 所說明的,在全域環境下的變數或函式沒有特別綁定 this
的狀況下,會指向預設綁定中的 window ,也就是全域物件(屬性),所以在這 callback function 中的 this
就會指向 全域物件(屬性) ,也就是 window。
let btn = document.querySelector(".btn") btn.addEventListener("click", function () {
console.log(this) //<button class="btn">我要學會 HTML!</button>
setTimeout(function () {
console.log(this) //window
},1000)
})
就如上述所說的,在 setTimeout()
的 callback function 中 this
就會指向 全域物件(屬性) ,也就是 window。
但可以透過另一個變數來儲存 this
方式。
let btn = document.querySelector(".btn")btn.addEventListener("click", function () {
let that = this
console.log(this) //<button class="btn">我要學會 HTML!</button>
setTimeout(function () {
console.log(this) //<button class="btn">我要學會 HTML!</button>
},1000)
})
可以將在監聽事件內以 that
變數儲存 this
,那麼在 setTimeout()
的 callback function 中則可以透過 that
變數來取得在監聽事件中的 this
。
上述範例除了之前介紹的 顯式綁定 (Explicit Binding)外,還可以透過這個方式取得在監聽事件中的 this
。
箭頭函式 =>
在 ES6 新增一種叫做 「箭頭函式」 (Arrow Function expression) 的函式表達式。
箭頭函式有個特點:強制綁定 this
。
從之前的範例中來說明 :
let obj = {
name: "Thomas",
age: 22,
funcA: function () {
console.log(this.age) //22
function funcB() {
console.log(this.age) //undefined
}
funcB()
}
}obj.funcA()
執行 obj.funcA()
函式可以發現到 funcA()
中的 this.age
指向 obj
物件中的 age
,但 funcB()
中的this.age
是指向全域物件中的 age
( 參考 : JavaScript #1 — 運算子、運算式、值與型別、變數
),因執行 funcB()
函式時,並沒有明確指定 this
要綁定哪個物件,會依照上述的 預設綁定給 全域物件 (window),那就是 window.age
回傳值為undefined
。
但如果使用 箭頭函式,如下 :
let obj = {
name: "Thomas",
age: 22,
funcA: function () {
console.log(this.age) //22
funcB = ()=> {
console.log(this.age) //22
}
funcB()
}
}obj.funcA()
此時 funcB()
中的this.age
就會強制綁定在 funcA()
中的 this.age
。
箭頭函式 會強制綁定 this
外,也有須要注意的事,在使用 嚴格模式下 (use strict) 與 再加上 bind()
都無法改變 this
指定的物件,更不能作為建構子來使用。
嚴格模式 (use strict)
在 嚴格模式下 funcB()
函式中的 this
會變成 undefined
。
let obj = {
name: "Thomas",
age: 22, funcA: function () {
"use strict"
console.log(this === obj) //true
function funcB() {
console.log(this) //undefined
}
funcB()
},
}obj.funcA()
…
參考:鐵人賽:JavaScript 的 this 到底是誰?、this 、 JavaScript this 、The JavaScript this Keyword
以上是我對 JavaScript # 10 — This (下) 的學習筆記 😉。
***如果有任何想法,也歡迎留言與我分享~***