> For the complete documentation index, see [llms.txt](https://shenjunhong.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://shenjunhong.gitbook.io/blog/yuan-ma/yuan-ma-shou-xie-xi-lie/bind.md).

# bind

bind 函数的实现，需要了解 this 的绑定。this 绑定有 4 种绑定规则: 默认绑定、 隐式绑定、 显示绑定、 new 绑定

```js
Function.prototype.myBind = function (context) {
  // 1. 保存原始函数
  let that = this;

  // 添加类型检查
  if (typeof that !== "function") {
    throw new TypeError("myBind must be called on a function");
  }

  // 2. 获取参数，从参数列表第一个开始获取，返回数组。获取除绑定的 this 之外的其他参数
  let bindArgs = Array.prototype.slice.call(arguments, 1);

  // 3. 返回一个新函数
  function fBound() {
    let args = Array.prototype.slice.call(arguments); // 获取调用时的参数
    return that.apply(
      this instanceof fBound ? this : context, // 如果是 new 调用，this 指向实例，否则指向 context
      bindArgs.concat(args) // 合并预设参数和调用时参数
    );
  }

  // 维护原型关系
  if (this.prototype) {
    // 此处获取原函数的原型，作为 fBound 的原型，维护原有的原型链
    fBound.prototype = Object.create(this.prototype);
  }

  return fBound;
};
```

我们最开始要绑定的函数称为 fToBind， 返回值称为 fBound， 从代码可以看到， bind 执行的结果并没有返回 fTobind，真正的待执行函数被封装在 fBound 里面。当我们绑定完成之后执行 fBound 的时候，在 fBound 内部 fToBind 会调用 apply 进行绑定并执行。而此时，apply 的第一个参数已经是确定下来的了。接下来分为两种情况，当判断到当前函数是被当成构造函数执行时，此时忽略强行绑定，保留 new 操作；第二种情况是正常绑定，即获取 bind 函数传入的 this 进行绑定。

原因在于 bind 函数返回了一个新的函数 fBound，fBound 执行时，内部 fToBind 绑定所需要的 this 都已经确定下来了，当我们进行二次绑定时，操作的对象已经是 fBound 了，此时再进行 bind 操作时，我们只能改变 fBound 的 this，但函数不作为构造函数执行时 fBound 内部的绑定操作并不依赖于 fBound 的 this，而是依赖于第一次传入的 oThis。所以不管我们再怎么绑定，都不能再改变绑定的结果了。

简单来说，再次 bind 的时候，我们已经无法对最原始的待绑定函数进行操作了，我们操作的只是它的代理。

// bind() 方法会创建一个新函数。当这个新函数被调用时，bind() 的第一个参数将作为它运行时的 this，之后的一序列参数将会在传递的实参前传入作为它的参数。(来自于 MDN )

```js
Function.prototype.bind = function (ctx, ...bindArgs) {
  // 保存当前函数(this)
  const fn = this;
  if (typeof fn !== "function") {
    throw new TypeError("myBind must be called on a function");
  }
  // 返回一个新函数
  return function fBound(...newArgs) {
    // 合并参数
    return fn.apply(
      this instanceof fBound ? this : ctx,
      bindArgs.concat(newArgs)
    );
  };
};
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shenjunhong.gitbook.io/blog/yuan-ma/yuan-ma-shou-xie-xi-lie/bind.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
