先来一段自定义的bind函数
//手写bind函数
Function.prototype.myBind=function(obj) {
if(typeof this != 'function') {
throw new TypeError('Error');
}
let _this = this;
let args = Array.prototype.slice.call(arguments,1);
return function F() {
if(this instanceof F) {
return new _this(...args,...arguments);
}
return _this.apply(obj,args.concat(...arguments))
}
}
然后我想什么情况下会让this instanceof F
为true?这个和new的内部实现其实有关。先定义一个构造函数,看一下出现的现象。
//定义一个构造函数
let Person = function (name, age) {
this.name = name;
this.age = age;
}
调用myBind函数出现的
let P1 = Person.myBind({},'zhangsan',12);//new的时候bind的第一个参数没什么用
let p1 = new P1(); //此时this在F的原型链上
let obj = {}; //不用new的时候bind的第一个参数有用,所以这里创建出来
let p2 =Person.myBind(obj,'zhangsan',12);
p2();//此时this不在F的原型链上
console.log(obj); //{name:'zhangsan',age:12}
具体为什么new的时候this在F的原型链上,需要结合new的内部实现来看
new的内部实现:
function myNew(fn,...args) {
let obj = {};
obj.__proto__ = fn.prototype;
fn.apply(obj,args);
return obj;
}
为什么 this instanceof F == true?
let P1 = Person.myBind({},'zhangsan',12);//这一步返回了myBind函数中的function F;
let p1 = new P1();
new P1()这一步的详细展开如下:
let obj = {};
obj.__proto__ = F.prototype;//这一步是关键,new会让新创建的对象原型指向构造函数的原型
F.apply(obj);//apply函数让F里面的this指向了obj,然后上面一行又设置了obj的原型指向F的原型;所以 this instanceof F == true;
return obj;