【前言】本系列为个人前端学习之路的学习笔记,在过往的学习过程中累积了很多笔记,如今想借着IT邦帮忙这个平台做整理+再复习。本系列标题一律以【】标示该篇文章主要涉及的内容,例如【JavaScript】、【Vue】等等。若内容有误,还麻烦各路大神不吝于点出问题,感激不敬。


为什么要使用 call / apply / bind

在撰写函式的时候,我们很常遇到这样的情况:

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

使用 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

apply

理解 call 的用法之后,apply 在运用上非常接近,只是调用参数上写法有所不同

fn1.call(family, 1, 2)
fn1.apply(family, [1, 2])

同样的案例,使用 apply 执行函式,一样可以带入一个 this,一样会立刻执行,但参数会以阵列的方式呈现换呈现apply 的第二个参数必须是阵列(或是没有参数的话可以不写,但写了就必须是阵列)不然会跳错

bind

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拿来用