【前言】
本系列為個人前端學習之路的學習筆記,在過往的學習過程中累積了很多筆記,如今想藉著IT邦幫忙這個平台做整理+再複習。
本系列標題一律以【】標示該篇文章主要涉及的內容,例如【JavaScript】、【Vue】等等。
若內容有誤,還麻煩各路大神不吝於點出問題,感激不敬。
在撰寫函式的時候,我們很常遇到這樣的情況:
let family = {
myName: '小明家',
callSomeone: function(){
let self = this
setTimeout(()=>{
console.log(self.myName)
}, 0)
}
}
在這段程式碼中,當我們執行 family.callSomeone() 時因為 setTimeout 是簡易呼叫,this 指向全域
因此我們需要透過宣告 self = this
因為 self 一定會向外尋找,而外層的 this 是指向 family 這個物件,這樣才能正確取到 family 底下的屬性
因為 this 的指向會變動
導致我們會必須額外寫點東西來讓 this 指向正確
而 call / apply / bind 最大的功能就是解決這個問題,即在函式執行時指定正確的 this
使用 call 執行函式,看起來會像是這樣:
let family = {
myName: '小明家'
}
function fn1(a, b){
console.log(this.myName, a, b)
}
fn1.call(family, 1, 2) //小明家 1 2
寫法是 函式.call(this, 參數 1, 參數 2 ......)
即在執行函式的時候,給予一個正確的 this 位置,進而讓執行結果正確
在這個案例中,透過 call 使得 fn1() 在執行時能夠正確取得在 family 物件內的 myName
理解 call 的用法之後,apply 在運用上非常接近,只是調用參數上寫法有所不同
fn1.call(family, 1, 2)
fn1.apply(family, [1, 2])
同樣的案例,使用 apply 執行函式,一樣可以帶入一個 this,一樣會立刻執行,但參數會以陣列的方式呈現換呈現
apply 的第二個參數必須是陣列(或是沒有參數的話可以不寫,但寫了就必須是陣列)不然會跳錯
bind 如同其名,用途是讓給你一個綁定 this 函式,而且這個 this 是綁死的
寫法是 函式.bind(this, 參數 1, 參數 2 ......)
重點在使用bind執行函式,他不會立刻執行,而且最後會回傳一個新的函式
const fn2 = fn1.bind(family, 1, 2) //不會立刻執行,沒有東西
fn2() //小明家 1 2
同樣一個案例,我們並不是像 call / apply 一樣去執行 fn1
而是將 fn1 的 this 跟 family 綁定後,將這個新的函式賦值到 fn2 上
最後,我們再執行這個綁好 this 的函式 fn2
並且 bind 會把參數強制寫進去,因此若我們執行 fn2(3, 4),得到的結果仍就是 1 和 2
但 bind 也可以只寫入部分的參數,例如只寫入 1,此時fn2(3, 4)其中的3就會被顯示出來(按順序補上),因為傳入了兩參數,但一個已經定義一個沒有,就自動把第一個3拿來用