ChuChencheng / note

菜鸡零碎知识笔记
Creative Commons Zero v1.0 Universal
3 stars 0 forks source link

JavaScript 实现 call, apply 与 bind #21

Open ChuChencheng opened 4 years ago

ChuChencheng commented 4 years ago

call

Function.prototype._call = function (thisArg) {
  if (typeof this !== 'function') {
    throw TypeError('Not callable')
  }
  if ((function () { return this })() !== undefined) {
    // 非严格模式
    if (thisArg == null) thisArg = window || global
    else if (typeof thisArg !== 'object' && typeof thisArg !== 'function') {
      // 原始值
      thisArg = new Object(thisArg)
    }
  }
  const symbol = Symbol('call')
  thisArg[symbol] = this
  const result = thisArg[symbol](...Array.from(arguments).slice(1))
  delete thisArg[symbol]
  return result
}

apply

Function.prototype._apply = function (thisArg, argsArray) {
  if (typeof this !== 'function') {
    throw TypeError('Not callable')
  }
  if ((function () { return this })() !== undefined) {
    // 非严格模式
    if (thisArg == null) thisArg = window || global
    else if (typeof thisArg !== 'object' && typeof thisArg !== 'function') {
      // 原始值
      thisArg = new Object(thisArg)
    }
  }
  const symbol = Symbol('apply')
  thisArg[symbol] = this
  const result = thisArg[symbol](...Array.from(argsArray))
  delete thisArg[symbol]
  return result
}

bind

Function.prototype._bind = function (thisArg) {
  if (typeof this !== 'function') {
    throw TypeError('Not callable')
  }
  const originalFunction = this
  const argsList = [].slice.call(arguments, 1)
  const bound = function () {
    argsList.push(...arguments)
    if (new.target !== undefined) {
      // new 了 bind 后的函数,走 new 的流程
      Object.setPrototypeOf(this, originalFunction.prototype)
      return originalFunction.call(this, ...argsList)
    } else {
      return originalFunction.call(thisArg, ...argsList)
    }
  }
  return bound
}

参考

https://github.com/francecil/leetcode/issues/10