Skip to content
🍭🍬🍧

apply

ECMA

js
1. Let func be the this value.
2. If IsCallable(func) is false, throw a TypeError exception.
3. If argArray is either undefined or null, then
 a. Perform PrepareForTailCall().
 b. Return ? Call(func, thisArg).
4. Let argList be ? CreateListFromArrayLike(argArray).
5. Perform PrepareForTailCall().
6. Return ? Call(func, thisArg, argList).

实现

js
Function.prototype.apply = function (boundThis, argsArray) {
  if (typeof this !== "function") {
    throw new Error("type error")
  }
  // 1. 如果 boundThis 是 null 或 undefined,
  // this 设置为全局对象(浏览器中是 window,Node.js 中是 global)
  const boundThis === null || boundThis === undefined
   ? globalThis : Object(boundThis)
  // 2. 创建一个唯一的临时属性名,避免与原对象上的属性冲突
  const fnKey = Symbol("fnKey")
   // 3. 将 this 函数作为 boundThis 的一个属性
  boundThis[fnKey] = this
  let result
  if(args) {
    // 4. 使用普通函数调用的方式执行目标函数,并传递参数
    // 保证 this(目标函数中的this) 指向 boundThis
    result = boundThis[fn](...argsArray)
  } else {
    result = boundThis[fn]()
  }
  // 5. 删除临时添加的属性
  delete context[fn]
  return result
}

使用

js
function sum(a, b, c) {
  return a + b + c
}

const boundThis = { value: "some context" } // 可以是任意对象
const boundArgs = [1, 2] // 绑定前两个参数

// 拼接绑定的参数和新的参数列表
const args = boundArgs.concat([3]) // [1, 2, 3]

// 调用自定义的 call 函数
const result = sum.apply(boundThis, args)
console.log(result) // 输出 6

Released under the MIT License.