JavaScript call()、apply()、bind()三个函数的备忘录

477 阅读2分钟

今天又是连续暴雨的一天,已连续下雨好几周了。房间里黑漆漆的,突然想到 JavaScript 的call()、apply()、bind()三个函数。。。人家都在想女友,而我此时此刻想到了代码,太惨了。。。一脸懵逼,还忘记了它们的区别,果然雨下得连脑子都不好使了。。。

  • 马上在浏览器写了一段代码验证一下三个函数有啥不同,如下:
let bigBaby = {
    name: '大宝',
    age: 81,
    ageFun: () => {
        console.log(this.name + "年龄:" + this.age)
    },
    descFun: (height , weight, hobby) => {
        console.log(this.name + "年龄:" + this.age + " 身高:" + height + "米 体重:" + weight + " 爱好:" + hobby)
    }
}

let littleBaby = {
    name: '小宝',
    age: 18
}

bigBaby.ageFun.call(littleBaby)    // undefined年龄:undefined
bigBaby.ageFun.apply(littleBaby)    // undefined年龄:undefined
bigBaby.ageFun.bind(littleBaby)()   // undefined年龄:undefined
  • 看到结果后,才晃过来bigBaby对象里的箭头函数作用域提升了,this指向window,所以取不到值undefined了。。。粗心容易犯错,别想着一写函数就写箭头函数。。。紧接着改成如下代码:
let bigBaby = {
    name: '大宝',
    age: 81,
    ageFun: function () {
        console.log(this.name + "年龄:" + this.age)
    },
    descFun: function (height , weight, hobby) {
        console.log(this.name + "年龄:" + this.age + " 身高:" + height + "米 体重:" + weight + " 爱好:" + hobby)
    }
}

let littleBaby = {
    name: '小宝',
    age: 18
}

bigBaby.ageFun.call(littleBaby)    // 小宝年龄:18
bigBaby.ageFun.apply(littleBaby)    // 小宝年龄:18
bigBaby.ageFun.bind(littleBaby)()      // 小宝年龄:18
  • 看到如下结果,就对了。第一点:

    • call()、apply()、bind() 三个函数都是用来重定义 this 这个对象的,把原本 bigBaby 的方法重定义为 littleBaby 的方法,所以读取到的 age 是 littleBaby 定义的 18 岁
    • call、apply 直接执行函数,bind 返回的是一个新的函数,所以要调用它才会被执行
  • 接着测试,代码如下:

let bigBaby = {
    name: '大宝',
    age: 81,
    ageFun: function () {
        console.log(this.name + "年龄:" + this.age)
    },
    descFun: function (height, weight, hobby) {
        console.log(this.name + "年龄:" + this.age + " 身高:" + height + "米 体重:" + weight + " 爱好:" + hobby)
    }
}

let littleBaby = {
    name: '小宝',
    age: 18
}

bigBaby.descFun.call(littleBaby, 2, '200斤', (() => '篮球')())    // 小宝年龄:18  身高:2米 体重:200斤 爱好:篮球
bigBaby.descFun.apply(littleBaby, [2, '200斤', (() => '篮球')()])   // 小宝年龄:18  身高:2米 体重:200斤 爱好:篮球
bigBaby.descFun.bind(littleBaby, 2, '200斤', (() => '篮球')())()      // 小宝年龄:18  身高:2米 体重:200斤 爱好:篮球
  • 看到如下结果,第二点:

    • 除了第一个参数,后面的参数都是函数的入参
    • call 的参数是直接放进去的,全都用逗号分隔,直接放到后面 bigBaby.descFun.call(littleBaby, 2, '200斤', (() => '篮球')())
    • apply 的所有参数都必须放在一个数组里面传进去 bigBaby.descFun.apply(littleBaby, [2, '200斤', (() => '篮球')()])
    • bind 的参数是直接放进去的,全都用逗号分隔,直接放到后面,和 call 一样 bigBaby.descFun.bind(littleBaby, 2, '200斤', (() => '篮球')())()
    • 三者的参数允许是各种类型
  • 总结

    • call()、apply()、bind() 三个函数都是用来重定义 this 这个对象的

    • call 和 bind 的函数入参参数都用逗号分隔传入函数中,apply 的函数入参参数要放在一个数组里面传入函数中