call()bind() 方法接受的是一个参数列表,apply() 方法接受的是一个参数数组。 bind() 方法返回原函数的拷贝,并有指定的 this 和参数

Function.prototype.myCall = function(context) {
  if (typeof context === 'undefined' || typeof context === 'null') {
    context = window
  }
  const symbol = Symbol()
  context[symbol] = this
  const args = [...arguments].slice(1)
  const result = context[symbol](...args)
  delete context[symbol]
  return result
}
Function.prototype.myApply = function(context) {
  if (typeof context === 'undefined' || typeof context === 'null') {
    context = window
  }
  const symbol = Symbol()
  context[symbol] = this
  let result
  // 处理参数和 call 有区别
  if (arguments[1]) {
    result = context[symbol](...arguments[1])
  } else {
    result = context[symbol]()
  }
  delete context[symbol]
  return result
}
Function.prototype.myBind = function (context) {
  if (typeof context === 'undefined' || typeof context === 'null') {
    context = window
  }
  const _this = this
  const args = [...arguments].slice(1)
  // 返回一个函数
  return function F() {
    // 因为返回了一个函数,我们可以 new F(),所以需要判断
    if (this instanceof F) {
      return new _this(...args, ...arguments)
    }
    // 这边的 apply 严谨点可以自己实现
    return _this.apply(context, args.concat(...arguments))
  }
}