05-javascript自己实现一个apply、call、bind

170 阅读2分钟

coderwwh w:what是什么? w:why为什么? h:how怎么样?

call()

step1:要让所有的函数都有这个方法

解答:放在原型上

// 给所有的函数添加方法
Function.prototype.Mycall = function(){
    //...
}

step2:要调用原函数

比如自己写了个sum()函数,sum.Mycall()

这里Mycall里的this就是sum

// 给所有的函数添加方法
Function.prototype.Mycall = function(){
    // 在这里可以去执行调用的那个函数(foo)
    // 问题: 得可以获取到是哪一个函数执行了mycall
    // 1.获取需要被执行的函数
    var fn = this
    fn()
}

step3:绑定this到传入的对象上

比如调用的时候,sum.Mycall({name:wwh})

// 给所有的函数添加方法
Function.prototype.Mycall = function(thisArg){
    // 在这里可以去执行调用的那个函数(foo)
    // 问题: 得可以获取到是哪一个函数执行了mycall
    // 1.获取需要被执行的函数
    var fn = this
    
    //调用需要被执行的函数
    thisArg.fn = fn
    thisArg.fn()
    delete thisArg.fn
}

step4:容错

万一调用的时候,sum.Mycall(123) 这时候thisArg.fn = fn,会报错,因为数字上面不能加属性啊

这时候需要用到装箱,但是还会有些弊端

// 给所有的函数添加方法
Function.prototype.Mycall = function(thisArg){
    // 在这里可以去执行调用的那个函数(foo)
    // 问题: 得可以获取到是哪一个函数执行了mycall
    // 1.获取需要被执行的函数
    var fn = this
    
    // 2.对thisArg转成对象类型(防止它传入的是非对象类型)
    thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
    
    //调用需要被执行的函数
    thisArg.fn = fn
    thisArg.fn()
    delete thisArg.fn
}

step5:参数

Function.prototype.hycall = function(thisArg, ...args) {
  // 在这里可以去执行调用的那个函数(foo)
  // 问题: 得可以获取到是哪一个函数执行了mycall
  // 1.获取需要被执行的函数
  var fn = this

  // 2.对thisArg转成对象类型(防止它传入的是非对象类型)
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window

  // 3.调用需要被执行的函数
  thisArg.fn = fn
  var result = thisArg.fn(...args)
  delete thisArg.fn

  // 4.将最终的结果返回出去
  return result
}

搞定!

apply()

//参考coderwhy老师的代码
// 自己实现hyapply
Function.prototype.hyapply = function(thisArg, argArray) { 
  // 1.获取到要执行的函数
  var fn = this

  // 2.处理绑定的thisArg
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window

  // 3.执行函数
  thisArg.fn = fn
  var result

  argArray = argArray || []
  result = thisArg.fn(...argArray)

  delete thisArg.fn

  // 4.返回结果
  return result
}

bind()

//参考coderwhy老师的代码
Function.prototype.hybind = function(thisArg, ...argArray) {
  // 1.获取到真实需要调用的函数
  var fn = this

  // 2.绑定this
  thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window

  function proxyFn(...args) {
    // 3.将函数放到thisArg中进行调用
    thisArg.fn = fn
    // 特殊: 对两个传入的参数进行合并
    var finalArgs = [...argArray, ...args]
    var result = thisArg.fn(...finalArgs)
    delete thisArg.fn

    // 4.返回结果
    return result
  }

  return proxyFn
}