实现bind方法
MDN文档指出:bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
1.首先bind方法会返回一个新的函数。在返回的新函数中调用call或apply方法来改变this指向。
Function.prototype.bind = function(obj) {
let self = this;
let args = [];
for(let i = 0; i < arguments.length; i++){
args[i] = arguments[i];
}
return function () {
return self.call(obj, ...args.splice(1), ...arguments);
}
}
2.当我们将bind后的函数当构造函数使用时,this绑定应该失效。
const a = 1;
let obj = {
a: 2
}
function func() {
thia.name = 'ltt';
console.log(this.a);
}
let f = func.bind(obj);
let o = new f(); // 2 ,实际应该输出underfind
new一个构造函数时,先会创建一个构造函数(f)的子类,然后返回对象o。当构造函数有返回值是对象或数组的时候,就会返回对象/数组;当有其他类型的返回值时,返回对象o。
let o = create Object();
o.__proto__ = f.prototype;
f.call(o);
return o;
所以,我们接着改造我们的bind方法。关键点是什么时候我们应该让this指向失效?也就是得判断什么时候把bind绑定函数当构造函数来用。
上边也提到了,new一个构造函数的时候,先创建一个它的子类o,然后调用call方法。call方法的执行的本质是将该构造函数f作为第一个参数o的方法,然后调用o.f(),使f函数内部的this指向o。而这里的f方法,就是bind中的返回的b方法。所以我们就可以用this来判断是否为o的实例,若是,说明bind方法被用来当构造函数使用的。
Function.prototype.bind = function(obj) {
let self = this;
let args = [];
for(let i = 0; i < arguments.length; i++){
args[i] = arguments[i];
}
function b() {
return self.call(this instanceof b ? this : obj, ...args.splice(1), ...arguments);
}
return b;
}
至此,bind函数就大致实现了。
实现call方法
Function.prototype.call = function(obj){
obj.func = this;
var res = obj.func(arguments);
delete obj.func;
return res;
}
网友评论