这是MDN上关于bind原理的一块代码,原网页链接:
var ArrayPrototypeSlice = Array.prototype.slice;
Function.prototype.bind = function(otherThis) {
var baseArgs= ArrayPrototypeSlice.call(arguments, 1),
baseArgsLength = baseArgs.length,
fToBind = this,
fNOP = function() {},
fBound = function() {
baseArgs.length = baseArgsLength; // reset to default base arguments
baseArgs.push.apply(baseArgs, arguments);
return fToBind.apply(
// {↓此行标记↓}
fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
);
};
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
return fBound;
};
在最后,fBound需要将调用bind的函数的prototype继承为自己的prototype,为什么不直接:
fBound.prototype = this.prototype;
而是绕了一大圈弄了个新函数:
var fNOP = function() {},
if (this.prototype) {
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
这么做的目的是什么呢?
by the way,在第一段的标记代码中:
// {此行标记}
fNOP.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
为什么使用fNop
来做instance
检测而不使用fBound
,这二者有什么区别吗?
劳驾答疑,不胜感激。
###第一个是为了解决引用类型问题。(借用构造函数进行继承)
第二个你要用fNop做继承难道拿fBound做检测吗?
先来举一个例子:
var obj = { name: "Martin" };
var hello = function(str){
console.log("Hello " + str + ' to ' + this.name);
};
var objHello = hello.bind(obj);
objHello('JS')
第一个问题:如果直接赋值?fBound
的 prototype
,hello
?函数的 prototype
也会被修改。因此,我们需要一个中间变量 fNOP
,让它等于一个空函数,通过 fNOP
来维护原型关系,并让 fBound.prototype
与 this.prototype
不再指向同一个原型函数。
第二个问题:我觉得应该使用 fBound
来检测,具体是将 fNOP.prototype.isPrototypeOf(this)
改成 this instanceof fBound
比如上面的代码最后改成用 new
调用
...
var newObj = new objHello('JS');
this instanceof fBound
中的 this
,如果是在 new
关键字调用情况下,会指向 newObj
,而 newObj
就是 fBound
的实例,this instanceof fBound
就是 true
,我们不再使用 otherThis
作为 hello
的 this
,而是直接使用 newObj
作为 hello
的 this
;而当做普通函数调用的时候,this instanceof fBound
就是 false
,hello
中的 this
依然指向 otherThis
。
以上,希望有所帮助 :)