JavaScript #10 — This (下)

Thomas Hung
Thomas 學習筆記
6 min readMay 18, 2020
Photo by sydney Rae on Unsplash

接續之前的 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 到底是誰?thisJavaScript thisThe JavaScript this Keyword

以上是我對 JavaScript # 10 — This (下) 的學習筆記 😉。

***如果有任何想法,也歡迎留言與我分享~***

--

--

Thomas Hung
Thomas 學習筆記

when you feel like quitting,think about why you started.