本文整理JavaScript Function.prototype下bind()、call()、apply()方法,亦可參見MDN連結。
Function.prototype.bind()
理解為「綁定」,要「綁定」something給前方的function
綁定什麼呢?
綁定前方這個function執行時,所需要的this和parameter
bind()的參數第一項一定是this,this可以為空值null,比如說你前方的function沒用到this.something,那就不需要特地綁this;第一項以後的參數,依序提供給前方的function作為parameter。
const printSubscription = function(){ console.log(this.subscription) } const pekora = { subscription:"145萬", age:111 } const showPekoraSubscription = printSubscription.bind(pekora) showPekoraSubscription() //145萬
bind()會建立一個新的Bound Function,因此和call()、apply()不同,綁完後是沒有包括執行這個新的Bound Function的
Function.prototype.call()
理解為「呼叫」,someFunction.call(this, arg1, arg2, ...)表示在呼叫執行someFunction時,給定this以及參數args
arg1、arg2、arg3等,依序填入給someFunction作為parameters
call()在各大前端框架中廣泛使用,MDN寫了兩種範例:物件建構子綁call()、匿名函數綁call()
物件建構子綁call()
function Vtuber(name, generation) { this.name = name; this.generation = generation; if (generation > 5 || generation < 0) throw RangeError("The generation is out of range."); return this; } function Hololive(name, generation) { Vtuber.call(this, name, generation); this.company = "Hololive"; } Hololive.prototype = new Vtuber() const Pekora = new Hololive("Pekora",3) console.log(Pekora) // Vtuber { name: 'Pekora', generation: 3, company: 'Hololive' }
匿名函數綁call()
const Vtubers = [ { name: "Pekora", generation: "3" }, { name: "Nene", generation: "5" }, ]; for (let i = 0; i < Vtubers.length; i++) { (function (i) { this.print = function () { console.log("# " + this.name + "is Hololive " + this.generation + " generation."); }; this.print(); }.call(Vtubers[i], i)); } // # Pekorais Hololive 3 generation. // # Neneis Hololive 5 generation.
Function.prototype.apply()
理解為「使用、套用」,someFunction.apply(this, [arg1, arg2, ...])表示在呼叫執行someFunction時,給定this以及陣列內的參數args。
跟call()的差別就在於call()的args是逗號區隔依序填入,但apply()是把args包一起放陣列內
function Hololive(name, generation) { Vtuber.apply(this, [name, generation]); this.company = "Hololive"; }