call | apply | bind三个转换指向的方法

100 阅读2分钟

这是我参与更文挑战的第1天,活动详情查看: 更文挑战

未进行函数调用的图片.png

当前方法中对于obj.objAge是因为objAge:this.age是在定义时候这个this指向的是window所以才是17,但是obj.myFun()是在执行的时候this指向了obj对象,但是由于当前对象中并没有age这个属性所以是undefined

这个三个主要都是用来重新定义this的指向问题的

函数的定义.png

callapply看起来使用方式是一样的,但是bind是返回了一个函数,再这次那个一次才能输出

函数参数的区别.png

call的参数(想要将this指向的对象,参数1,参数1...);

apply的参数(想要将this指向的对象,[参数1,参数1,....])

bind的参数(想要将this指向的对象)(参数1,参数2,参数3) 总结:

这个三个方法都是用来改变this指向的,但是callapply方法都是立即执行函数,在调用了call之后就会立即执行被指定的方法。但是bind是返回一个函数,可以在任何时候被调用

Call的源码实现过程

call的使用代码

var demo = {
  name:"账户",
  age:16
}
var demo2 = {
  name :'demo2',
  age:12,
  getAge:function(){
    console.log(this.age)
  }
}
demo2.getAge() // 未使用call的时候 12
demo2.getAge.call(demo) // 使用call函数之后 16 ,其中的this指向了demo对象

myCal的实现流程

  • 如何将myCall函数绑定到demo2.getAge方法上

    • myCall方法绑定到函数的原型上

    • Function.prototype.myCall = myCall
      
  • 如何在myCall中获取到demo2.getAge方法

    • 该方法在可以在函数内部的this中获取到

    • function myCall(obj){
        obj.myFunc = this
      }
      
  • 如何在myCall方法中直接值函数呢?

    • 直接在函数内容调用方法就好了

    • function myCall(obj){
        obj.myFunc = this
        obj.myFunc()
      }
      
  • 现在执行完成之后传入参数的对象中多了个myFunc方法

    • 直接函数内删除方法即可

    • function myCall(obj){
        obj.myFunc = this
        obj.myFunc()
        delete obj.myFunc
      }
      
  • 避免myFunc会覆盖Function.property中原有的方法

    • Symbol可以确保方法名称是唯一,不会覆盖原型中的其他方法

      let name = Symbol(new Date().getTime())
      obj[name] = this
      
  • 对于getAge中的函数如果存在参数的话

    • 获取传入的参数放置到内部函数中

    • let args = [...arguments].slice(1)
      obj[name](...args)
      

全部代码

function myCall(obj){
  let name = Symbol(new Date().getTime())
  obj[name] = this
  let args = [...arguments].slice(1)
  obj[name](...args)
  delete obj[name]
}
Function.prototype.myCall = myCall

var demo = {
  name:"账户",
  age:16
}

var demo2 = {
  name :'demo2',
  age:12,
  getAge:function(args1,args3){
    console.log(this.age,args1,args3)
  }
}
demo2.getAge.myCall(demo,3,4,5,56)

Apply方法的实现

function myCall(obj){
  let name = Symbol(new Date().getTime())
  obj[name] = this
  let args = arguments[1] || []
  obj[name](...args)
  delete obj[name]
}

Bind方法的实现

  • 之前绑定方法的方式和call方法的实现一样

    function myBind(obj){
      let fn = this
      return function(...newsArray){
        return fn.apply(obj,newsArray)
      }
    }