请手动实现一个 bind 函数。

推荐答案

-- -------------------- ---- -------
------------------------- - ----------------- -------- -
  -- ------- ---- --- ----------- -
    ----- --- ---------------------------------- - ---- -- ------ -- -- ----- -- --- -----------
  -

  ----- ---- - ----- -- -------
  ----- ---- - ---------- --- -- ---------
  ----- ------ - ---------------------- -
      -- ---- ---------- ------ ------- --- --
    ------ --------------- ---------- ------ - ---- - -------- ------------------------
  --


  -------------------
    -------------- - --------------
  -
  ---------------- - --- ------- -- -----

  ------ -------
--

本题详细解读

1. bind 函数的作用

bind() 方法会创建一个新的函数,当这个新函数被调用时,它的 this 关键字会被设置为传入的第一个参数,后续的参数将作为新函数的参数传递。bind 函数本质上是改变了函数执行时的 this 指向。

2. 实现步骤分解

  1. 参数检查:

    • 判断调用 myBind 的是否是函数,如果不是,抛出 TypeError 错误。
  2. 保存原函数和 context

    • self 保存原函数 this 的引用,后续需要用 apply 调用。
    • context 就是 bind 方法的第一个参数,它将作为新函数执行时的 this 上下文。
  3. 处理预置参数:

    • 使用 ...args 获取 bind 时传入的预置参数。
  4. 创建 fNOP 空函数:

    • 用于原型继承,避免修改原函数的原型。
  5. 创建返回函数 fBound

    • 这是 bind 方法返回的新函数。
    • 使用 ...boundArgs 获取新函数调用时传入的参数。
    • 处理 this
      • 判断是否使用 new 调用:
        • 如果 this instanceof fBoundtrue, 说明是用 new 调用的,此时 this 就是要返回实例对象,不需要改变 this
        • 否则就用 context 作为 this 上下文。
      • 使用 apply 方法调用原函数 self,并合并预置参数 args 和新参数 boundArgs
  6. 处理原型链:

    • 为了保证 new fBound() 返回的对象能继承原函数的原型属性,需要进行原型链的连接。
      • 首先,判断原函数是否有 prototype,没有就忽略原型链继承。
      • fNOP 的原型指向原函数的原型。
      • fBound 的原型指向 fNOP 的实例。
  7. 返回新函数 fBound

    • 将新创建的 fBound 返回,该函数的 this 和参数都被绑定了。

3. 为什么要使用 fNOP 空函数

如果直接让 fBound.prototype = this.prototype,会造成原型链的指向问题,当修改 fBound.prototype 时, this.prototype 也会被影响。 例如:

-- -------------------- ---- -------
  -------- -------------
    --------- - ----
  -

  ------------------------- - -----------
    --------------------
  -


  ----- ------------ - ------------------------

  ----------------------------- - -----------
    ------------------
  -
  ----- - - --- --------------
  -------------- -------------------------------- --------------------
  ----------------------------- -------------------------

如果使用fNOP 空函数,则只改变了fBound的原型,不会影响原函数Person的原型。

-- -------------------- ---- -------
  -------- -------------
    --------- - ----
  -

  ------------------------- - -----------
    --------------------
  -


  ----- ------------ - --------------------------

  ----------------------------- - -----------
    ------------------
  -
  ----- - - --- --------------
  -------------- -----------------------
   ----------------------------- -------------------------

4. 兼容 new 调用的情况

当使用 new 关键字调用 bind 返回的函数时, this 应该指向新创建的对象实例。因此需要判断是否使用 new 调用。

5. 核心要点

  • this 指向的理解:
    • 普通函数调用:this 指向调用该函数的对象(在严格模式下,没有对象调用,this 指向 undefined)。
    • bind 调用:this 指向 bind 函数第一个参数。
    • new 调用:this 指向新创建的对象实例。
  • 使用 apply 方法: 用于改变函数执行的 this 上下文,并传递参数。
  • 原型链继承: 为了保证 new 调用的情况下 bind 函数返回的新函数能够继承原函数的原型属性。
纠错
反馈