3.bind 实现/手写 bind

书诚小驿2024/10/01前端面经JavaScript

一、bind 是什么

bindJavaScriptFunction 原型上的一个方法,用于创建一个新的函数。这个新函数在被调用时,会将其 this 值绑定到指定的上下文对象,并且可以预设部分参数。

const boundFunction = originalFunction.bind(thisArg, arg1, arg2, ...);
  • originalFunction:需要绑定的原函数
  • thisArg:绑定到新函数的 this 值。
  • arg1, arg2, ...:可选参数,这些参数会在新函数被调用时作为原函数的参数预设

二、bind 的用途

1、绑定 this 上下文

在 JavaScript 中,this 的值在函数调用时动态绑定,这可能会导致意外的 this 值。使用 bind 可以确保函数在被调用时 this 指向正确的对象。

const person = {
  name: "World",
  greet: function () {
    console.log(`Hello, ${this.name}`);
  },
};

const greet = person.greet;
greet(); // 输出:Hello, undefined

const boundGreet = person.greet.bind(person);
boundGreet(); // 输出:Hello, World

2、预设参数

bind 可以预设部分参数,这样在调用新函数时,这些参数已经设置好了,可以减少重复代码。

function logMessage(timestamp, message) {
  console.log(`[${timestamp}] ${message}`);
}
//  null表示this指向Windows,第二个代表预设的第一个参数
const logWithCurrentTime = logMessage.bind(null, new Date().toISOString());
// Hello, world!第二个参数
logWithCurrentTime("Hello, world!");
// 输出:[2025-02-25T12:00:00.000Z] Hello, world!

3、创建构造函数

如果通过 new 调用 bind 返回的新函数,它会创建一个新的实例,并将 this 指向这个新实例。

function Person(name) {
  this.name = name;
}

const PersonWithDefaultName = Person.bind(null, "world");
const person = new PersonWithDefaultName();
console.log(person.name); // 输出: world

4、事件处理

在事件处理中,bind 可以确保事件处理函数的 this 指向正确的对象。

const button = document.createElement("button");
button.textContent = "Click me";

const handler = {
  handleClick() {
    console.log(`Button clicked by ${this.name}`);
  },
  name: "muying",
};

button.addEventListener("click", handler.handleClick.bind(handler));
document.body.appendChild(button);

三、bind 实现/手写 bind

提示

DETAILS
  1. 获取原函数和参数:通过 this 获取原函数,通过 Array.prototype.slice.call(arguments, 1) 获取从第二个参数开始的参数列表,这些参数是用户在调用 bind 时预先传入的。
  2. 返回新函数:返回一个新函数,这个新函数在被调用时会根据调用方式(是否通过 new)来决定 this 的指向。
  3. 处理参数合并:在新函数被调用时,获取调用时传入的参数,并将这些参数与 bind 时传入的参数合并。
  4. 支持 new 调用:如果新函数是通过 new 调用的,那么需要将原函数作为构造函数,并将 this 指向新创建的实例。如果不是通过 new 调用的,则将 this 指向 bind 时指定的上下文。

参考答案

DETAILS
Function.prototype.myBind = function (context) {
  // 获取原函数
  const fn = this;
  // 获取从第二个参数开始的参数列表
  const args = Array.prototype.slice.call(arguments, 1);

  // 返回一个新函数
  return function () {
    // 获取调用新函数时传入的参数
    const newArgs = Array.prototype.slice.call(arguments);
    // 将原函数的参数和新函数的参数合并
    const finalArgs = args.concat(newArgs);
    // 判断是否通过 new 调用了新函数
    if (this instanceof fn) {
      // 如果是通过 new 调用的,则将原函数作为构造函数,并将 this 指向新创建的实例
      return new fn(...finalArgs);
    } else {
      // 如果不是通过 new 调用的,则将原函数的 this 指向指定的上下文
      return fn.apply(context, finalArgs);
    }
  };
};
最后更新时间' 2025/3/9 18:24:05