bind
是ECMA5
中才出现的方法,IE8等低版本浏览器并不支持,所以在MDN中有了这样的一段代码:
if (!Function.prototype.bind) { //如果低版本浏览器不支持bind
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") { //如果this不是一个函数,抛出错误
// 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), //arguments为bind()括号中的参数
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments))); //argument 为bind返回方法运行时候的参数
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
在理解的时候,加了一些注释。但是其他的一段代码不知道为什么(或者修补什么情况)存在:
fNOP = function () {} //只是为了单纯复制this的原型链?
this instanceof fNOP && oThis ? this : oThis || window //经测试,this instanceof fNO一直返回false,所以等价于 oThis || window,那为什么存在?
fNOP.prototype = this.prototype; //?
fBound.prototype = new fNOP();//?
按照我的理解,觉得以下代码也可以满足需要:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
throw new TypeError("bind function error");
}
var aArgs = Array.prototype.slice.call(arguments,1),
fToBind = this,
fBound = function () {
return fToBind.apply(oThis || window,aArgs.concat(Array.prototype.slice.call(arguments)));
};
return fBound;
};
}
下面测试代码,好使:
var obj = {
name : 'name1',
say : function (arg1, arg2) {
console.log(this.name, arg1, arg2)
}
}
var foo = {
name : 'name2'
}
obj.say.bind(foo, '必定显示1', '必定显示2')('没有位置不显示了1', '没有位置不显示了2') // name2 必定显示1 必定显示2
能给个比较清楚的解释吗?
我把部分代码的位置调整了一下,更方便看明白具体工作原理:
下面是我加工过的一个版本,更加接近原生的Function.prototype.bind的特性: