剛開始學 Javascript 的人,一定跟我一樣,不知道this
到底在做什麼?即便現在,我還是不是很明白什麼情況該 this,但就算不明白,我們還是可以先了解,this 到底指向什麼東西。
MDN 上寫說:
this 值由被呼叫的函式來決定。它不能在執行期間被指派,每次函式呼叫調用的值也可能不同。
我們要先知道,this 不會永遠指向同一個東西,會取決於函式被呼叫的方式及環境。
在全域環境執行,或直接呼叫函式 this 會指向全域
// 全域環境執行
console.log(this) // window
// 直接呼叫函式
function foo(){
console.log(this)
} // undefined
全域環境執行中執行,不管是否是嚴格環境,都會顯示 window。
直接呼叫函式在嚴格模式中會顯示 undefined ,非嚴格模式會顯示 window。
使用物件來調用 this,this 會指向該物件。
let introduce = {
name: "Chloe",
greeting: function() {
console.log('Hi, my name is', this.name)
}
}
introduce.greeting() // Hi, my name is Chloe
調用 introduce.greeting() 的時候,.greeting()
是作用在 introduce 的環境中,因此 this 會指向 introduce 這個物件。
但如果使用間接呼叫的話,this 就會退回 global 的環境。我們來看看以下的例子。
let introduce = {
name: "Chloe",
greeting: function() {
console.log('Hi, my name is', this.name)
}
}
let sayHi = introduce.greeting
sayHi() // Hi, my name is undefined
因為sayHi()
是直接在 global 環境中呼叫,因此this會指向 global 。
可以使用 apply/call/bind 來綁定 this
透過 apply/call/bind 的方法來強制指定我們要的 this 是什麼。
我們同時看看 call 和 apply 的用法:
fun.call(thisArg,arg1,arg2,arg3)
fun.apply(thisArg,[arg1,arg2,arg3])
call 和 apply 的用法很像,傳出來的都是 function 執行的結果。
- thisArg:要傳進去的 this 是誰
- arg1,arg2,arg3:要帶進 function 的參數
唯一差別是 apply 參數傳入的方式是陣列。
const people = {
name: "Chloe",
}
function introduce(age,like) {
console.log(
`Hi, my name is ${this.name},
I am ${age} years old.
I like ${like}.`)
}
introduce.call(people,18,'apple')
introduce.apply(people,[18,'apple'])
// Hi, my name is Chloe,
// I am 18 years old.
// I like apple.
call 和 apply 的 this 還是有可能被改變,而 bind 則是硬繫結,綁定之後的 this 就沒辦法在更改。另外,bind 會回傳一個綁定好的函式。
const people = {
name: "Chloe",
}
function introduce(age,like) {
console.log(
`Hi, my name is ${this.name},
I am ${age} years old.
I like ${like}.`)
}
let speeking = introduce.bind(people,18,'apple')
speeking()
// Hi, my name is Chloe,
// I am 18 years old.
// I like apple.
this 會指向使用 new 建立的實體物件
let name = 'global'
class People {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`Hi, my name is ${this.name}.`);
}
}
let newPeople = new People('chloe')
newPeople.sayHi()
使用箭頭函式讓 this 指向函式環境
let introduce = {
name: "Chloe",
greeting: function() {
const arrow = () => {
updateName()
console.log('Hi, my name is', this.name)
}
const updateName = ()=> {
this.name = 'Amy'
}
arrow()
}
}
introduce.greeting() // Hi, my name is Chloe
執行arrow()
的環境是在greeting()
下,因此arrow()
的環境就是greeting()
的 this,因此 this.name 會指向 introduce 中的 name。
為什麼要用 this?
在越複雜的環境,如果傳入明確的參數的話,通常會比 this 的執行環境更加複雜。
參考資料:
JavaScript this 用法整理
this 是什麼? – 談談JavaScript的this
JavaScript 中的 this 是什麼?
MDN-this