this
是一個根據使用位置有不同值的關鍵字。不了解 JavaScript 中這個微小的細節可能會帶來很多困擾,所以花五分鐘的時間來學習所有的技巧是值得的。
this
在嚴格模式下
在任何物件之外,在嚴格模式下,this
的值總是 undefined
。
請注意,我提到了嚴格模式。如果未啟用嚴格模式(如果你的文件頂部沒有明確添加 'use strict'
),你將處於所謂的松散模式,而 this
- 除非下面特殊情況中提到的 - 將具有全局物件的值。
這意味著在瀏覽器上下文中是 window
。
方法中的 this
方法是附加到物件的函式。
你可以以各種形式看到它。
以下是其中一種:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
car.drive()
//Driving a Ford Fiesta car!
在這種情況下,使用一般函式,this
會自動綁定到物件。
注意:上述的方法宣告與 drive: function() {
… 是相同的,只是比較簡短:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive: function() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
在這個例子中也是一樣的:
const car = {
maker: 'Ford',
model: 'Fiesta'
}
car.drive = function() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
car.drive()
//Driving a Ford Fiesta car!
箭頭函式不以相同的方式工作,因為它們是以語法為基礎的:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive: () => {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
car.drive()
//Driving a undefined undefined car!
綁定箭頭函式
你無法像普通函式一樣綁定值到箭頭函式。
這是因為它們的工作方式不同。this
是以語法為基礎綁定的,這意味著它們的值是從它們被定義的上下文中衍生出來的。
明確地將一個物件傳遞給 this
以用作綁定
JavaScript 提供了幾種方式來將 this
映射到你想要的任何物件上。
在函式聲明步驟中使用 bind()
:
const car = {
maker: 'Ford',
model: 'Fiesta'
}
const drive = function() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}.bind(car)
drive()
//Driving a Ford Fiesta car!
你也可以綁定一個現有物件的方法以重新映射它的 this
值:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
const anotherCar = {
maker: 'Audi',
model: 'A4'
}
car.drive.bind(anotherCar)()
//Driving a Audi A4 car!
在函式調用步驟中使用 call()
或 apply()
:
const car = {
maker: 'Ford',
model: 'Fiesta'
}
const drive = function(kmh) {
console.log(`Driving a ${this.maker} ${this.model} car at ${kmh} km/h!`)
}
drive.call(car, 100)
//Driving a Ford Fiesta car at 100 km/h!
drive.apply(car, [100])
//Driving a Ford Fiesta car at 100 km/h!
你傳遞給 call()
或 apply()
的第一個參數始終會綁定到 this
。call()
和 apply()
之間的區別只是第二個期望參數列表是一個陣列,而第一個接受可變數量的參數,作為函式引數傳遞。
瀏覽器事件處理程序的特殊情況
在事件處理程序回調中,this
參考到接收到事件的 HTML 元素:
document.querySelector('#button').addEventListener('click', function(e) {
console.log(this) //HTMLElement
}
你可以使用以下方式綁定它:
document.querySelector('#button').addEventListener(
'click',
function(e) {
console.log(this) //Window(如果全局),或你的上下文
}.bind(this)
)