call、apply、bind区别及实现

119 阅读1分钟

以下均参照网上资料,其中:bind方法为自己总结

传参方式:

call: b.call(this,'参数1','参数2',...)       一个一个传参
apply: b.apply(this,['参数1','参数2',...])   数组传参
bind: b.bind(this)('参数1','参数2',...)      bind是创建一个改变了this指向的新函数

例:

let Person = {
    name: '名字呀',
    say(age,gender) {
        console.log('姓名是', this.name, '年龄是', age, '性别是', gender)
    }
}
let Person1 = { name: '名字111' }

实现一个call: // 原理:给要改变this指向的对象,给其添加想调用的方法,执行后删除

Function.prototype.myCall = function (context) {
    context = context || window // 考虑到myCall可能没传参
    const fn = new Date().getTime().toString(32)
    context[fn] = this // 将方法传过去
    let arg = [...arguments].slice(1) // 拿到参数[18,'女']
    context[fn](...arg) // 执行函数Person1.say,并依次传参
    delete context.fn // 删掉
}
Person.say.myCall(Person1, 18, '女') // 输出结果:姓名是 名字111 年龄是 18 性别是 女

实现一个apply:和call方法一样,但传参方式不同

let arg = arguments[1]

实现一个bind:返回一个绑定this的函数,接收多个参数

  • 法一:和实现call方法相似,并利用闭包给要指向的对象添加相应方法并执行
    
    Function.prototype.myBind = function (context) {
      let self = this 
        return function (...arg) {
          let fn = new Date().getTime().toString(32)
          context[fn] = self
          console.log('context=', context)
          return context[fn](...arg)
      }   
    }
    Person.say.myBind(Person1)(188, '女') 
    
  • 法二:利用闭包,转成apply形式调用
    
    Function.prototype.myBind = function (context) { // context为Person1对象
        let self = this
        return function () {
            self.apply(context, arguments)
        }
    }