if(!Function.prototype.bind){javascript
Function.prototype.bind = function(oThis){php
if(typeof this !=="function"){ //若是不函数抛出异常java
throw new TyperError("")数组
}app
var aArgs = Array.prototype.slice.call(arguments,1), //此处的aArgs是除函数外的参数函数
fToBind = this, //要绑定的对象ui
fNOP = function(){},this
fBound = function(){spa
return fToBind.apply(prototype
this instanceof fNOP ? this:oThis||this,aArgs.concat(Array.prototype.slice.call(arguments)));
)
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
}
明白 bind
的用法就必需要知道 apply
的用法,MDN 指出,apply
是直接修改了函数内部的指向到第一个参数,并将第二个参数数组传参进函数并运行这个函数。也就是说
var obj = {test: function() { console.log(this, arguments) }}, func = obj.test; obj.test("Hello", ",", "world", "!"); func.apply(obj, ["Hello", ",", "world", "!"]);
这两种运行方式是同样的。那么回到 Polyfill 中发现参数的写法是 args.concat(slice.call(arguments))
。args
是将 bind
时候定义的除第一个参数外的其它参数,而此时的 arguments
是指函数调用时候的参数,经过数组的操做将这两个参数合并成一个数组传入函数内部。看个例子你可能更容易明白:
/** 代码接上 **/ var newFunc = func.bind(obj, "Hello", ","); newFunc("world", "!");
那么再来回答问题一,这个是典型的属性继承的方法,原本使用
bound.prototype = self.prototype
就能够将原属性集成过来了,可是这样两个对象属性都指向同一个地方,修改 bound.prototype
将会形成 self.prototype
也发生改变,这样并非咱们的本意。因此经过一个空函数 nop
作中转,能有效的防止这种状况的发生。
bind返回的是函数
if (!Function.prototype.bind) {
Function.prototype.bind = function(obj) {
var _self = this ,args = arguments; return function() { _self.apply(obj, Array.prototype.slice.call(args, 1)); } } }