bind 函数的实现,需要了解 this 的绑定。this 绑定有 4 种绑定规则: 默认绑定、 隐式绑定、 显示绑定、 new 绑定
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;
};
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)
);
};
};