Call代码实现

// 自己实现的调用
Function.prototype.zyCall = function (thisArg, ...argArray) {

    var fn = this //这是指的是被调用的函数 foo()
    thisArg = Object(thisArg) //为了让第一个传入的是一个对象
    thisArg.fn = fn //赋值给{}方法为fn,这里fn的方法为foo()
    var result = thisArg.fn(...args) 
    delete thisArg.fn // 防止内存泄漏
    return result //返回出去这个函数的调用

}

function foo(num, max) {
    console.log("foo函数被调用了", this, num, max);
    return num + max
}

// function sum(min, max) {
//     return min + max
// }
// foo.call({},)
console.log(foo.zyCall({}, 1, 2));

apply实现

Function.prototype.zyapply = function(thisArg, argArray) {
  // 1.获取到要执行的函数
  var fn = this

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

  // 3.执行函数
  thisArg.fn = fn
  var result
  // if (!argArray) { // argArray是没有值(没有传参数)
  //   result = thisArg.fn()
  // } else { // 有传参数
  //   result = thisArg.fn(...argArray)
  // }

  // argArray = argArray ? argArray: []
  argArray = argArray || []
  result = thisArg.fn(...argArray)

  delete thisArg.fn

  // 4.返回结果
  return result
}

bind

Function.prototype.zybind = 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
}

Q.E.D.