3.bind 实现/手写 bind
一、bind 是什么
bind
是 JavaScript
中 Function
原型上的一个方法,用于创建一个新的函数。这个新函数在被调用时,会将其 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
- 获取原函数和参数:通过 this 获取原函数,通过 Array.prototype.slice.call(arguments, 1) 获取从第二个参数开始的参数列表,这些参数是用户在调用 bind 时预先传入的。
- 返回新函数:返回一个新函数,这个新函数在被调用时会根据调用方式(是否通过 new)来决定 this 的指向。
- 处理参数合并:在新函数被调用时,获取调用时传入的参数,并将这些参数与 bind 时传入的参数合并。
- 支持 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);
}
};
};