标准答案

  1. call 接收 thisArg 和参数列表,apply 接收 thisArg 和参数数组。
  2. 实现 call/apply 可以把函数临时挂到 thisArg 上调用,再删除临时属性。
  3. thisArg 为 null 或 undefined 时,非严格模式下通常指向全局对象。
  4. bind 返回新函数,不会立即执行,并支持预置参数。
  5. bind 返回的函数被 new 调用时,this 应该指向新实例,而不是绑定时传入的对象。

题目解析

这道题考的是 this 绑定规则。call/apply 改变的是本次调用的 this,bind 改变的是未来调用的 this,并且可以提前固定一部分参数。

临时属性调用法能解释为什么 this 会指向目标对象:函数作为对象方法被调用时,方法内部 this 指向这个对象。为了避免属性名冲突,应该使用 Symbol 作为临时 key。

bind 的 new 规则是常见进阶点。绑定函数作为构造函数使用时,绑定的 thisArg 会被忽略,但预置参数仍然生效。

代码示例

下面是核心行为版本,重点展示 this 绑定、参数传递和 bind 的构造调用边界。

JavaScript
function myCall(fn, thisArg, ...args) {
  const context = thisArg == null ? globalThis : Object(thisArg)
  const key = Symbol('fn')

  context[key] = fn
  const result = context[key](...args)
  delete context[key]

  return result
}

function myApply(fn, thisArg, args = []) {
  return myCall(fn, thisArg, ...args)
}

function myBind(fn, thisArg, ...presetArgs) {
  function bound(...args) {
    const isNew = this instanceof bound
    const context = isNew ? this : thisArg
    return fn.apply(context, [...presetArgs, ...args])
  }

  bound.prototype = Object.create(fn.prototype)
  return bound
}

常见误区

  • bind 写成直接执行函数,忘记它应该返回新函数。
  • call/apply 临时属性名使用普通字符串,可能覆盖目标对象已有属性。
  • 没有处理 bind 返回函数被 new 调用时的 this 规则。

作者信息