参考MDN
task1:判断Function.prototype.bind是否存在, 如果存在,不重写,不存在,需要重写
if(!Function.prototype.bind){
Function.prototype.bind = function(obj){}
}
task2: 调用到时候,例如func.bind(),需要判断func 是不是个函数,如果不是,报错。注意,bind方法的this是隐式绑定,指向func.
if(typeof this !== 'function'){
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
task3: 参数分割,调用方式func.bind(obj, arg1)(arg2) 等价于func.bind(obj)(arg1,arg2)
//参数一
var args1 = Array.prototype.slice.call(arguments,1);
//参数二
var args2 = Array.prototype.slice.call(arguments);
var args = args1.concat(args2)
task4: 有两种bind的用法,一种是func.bind(obj)(arg), 一种是 new func.bind(obj)(arg),其中,后者的obj参数默认作废,等同于new func(arg),这是由于new的绑定优先级高于bind的缘故。所以,执行的时候需要判断是不是new方式执行
Function.prototype.bind = function(obj){
...
//第二种方式 new 的时候,第一步会创建一个空的对象,该对象的_proto_指向构造函数的prototype, 因此该对象.instanceof(构造函数)===true
//第二步会将this指向这个空对象,并执行以下构造函数func内容。
//在构造函数里可以用this.instanceof(fBound)判断是否是new方式执行,如果不是,说明是第一种方式执行,this指向参数obj
var fBound= function(){
var _this = this.instanceof(fBound) ? this : obj;
}
}
task5: 维护原型关系
new的时候,新对象的_proto_指向构造函数的prototype。期望新对象的原型链向上查找能够找到func.prototype
var fNOP = function(){}
if(this.prototype){
fNOP.prototype=this.prototype
}
fBound.prototype = new fNOP()
// 新对象._proto_ = fBound.prototype
//fBound.prototype._proto_=fNOP.prototype=this.prototype
代码
if(!Function.prototype.bind){
Function.prototype.bind = function (obj) {
if(typeof this !== 'function'){
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var args1 = Array.prototype.slice.call(arguments,1);
var fToBind = this;
var fBound = function(){
var args2 = Array.prototype.slice.call(arguments);
var args = args1.concat(args2);
var _this_ = this.instanceof(fBound)? this : obj;
fToBind.apply(_this_, args);
}
var fNOP = function(){};
if(this.prototype){
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP():
}
return fBound;
}
网友评论