今天研究了一下es5中的bind函数如何用es3的语法来实现,下面是一个简单的bind函数实现:
bind函数
Function.prototype.bind=function(oThis){
var self=this;
var args=Array.prototype.slice.call(arguments,1);
var result=function(){
return self.apply(oThis,args.concat(Array.prototype.slice.call(arguments)));
};
var temp=function(){};
temp.prototype=this.prototype;
result.prototype=new temp();
return result;
};
测试代码
var A={
name: 'jc',
print: function(title){
console.log(title+this.name);
}
};
var func=A.print.myBind(A);
func('red'); //jcred
分析
整个bind函数一共做了两件事:
首先通过数组的原型方法把bind函数参数中除了oThis对象以外的参数保存到args中,然后再讲args和调用函数传入参数列表合并,并通过调用Function.prototype.apply方法将oThis绑定到调用函数的this上,并传入合并后的参数列表。
因为调用apply方法返回了一个新的函数对象,丢失了原函数对象的原型属性,所以还要将新的函数对象的prototype属性引用原函数对象的原型对象。
之所以不采用result.prototype=this.prototype这种写法,而是使用了一个中间层对象temp,是因为不想通过修改result.prototype就修改了原函数对象的原型对象。
附上bind函数官方文档的实现
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}