bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind()的第一个参数,而其余参数将作为新函数的参数,供调用时使用
Function.prototype._bind = function(thisArg, args){
if(typeof this !== 'function'){
throw new TypeError('Bind must be called on a function')
return
}
const me = this
// new 优先级
const bindFn = function(){
// 判断是否用 new 调用 bindFn,决定最终的this指向
// this instanceof me:判断bindFn是否被当作构造函数(new调用)
// 是new调用:this指向bindFn的实例,此时this应该绑定到实例本身
// 不是new调用:this绑定到传入的thisArg
// 参数拼接:绑定阶段的args + 调用阶段的arguments(实现柯里化)
me.apply(this instanceof me ? this : thisArg, args.concat(Array.prototype.slice.call(arguments)))
}
// 让绑定后的函数继承原函数的原型(保证实例能访问原函数原型的属性)
bindFn.prototype = Object.create(me.prototype)
// 返回绑定后的新函数(bind的核心特性:不立即执行,返回新函数)
return bindFn
}
function Person(name) {
this.name = name;
}
const obj = { name: 'test' };
const BindPerson = Person._bind(obj);
// 普通调用:this指向obj
BindPerson('张三');
console.log(obj.name); // 张三
// new调用:this指向实例,obj不受影响
const p = new BindPerson('李四');
console.log(p.name); // 李四
console.log(obj.name); // 张三