bind()
函數是在 ECMA-262 第五版才被加入;它可能沒法在全部瀏覽器上運行。這就須要咱們本身實現bind()
函數了瀏覽器
簡單實現bind()
方法:app
Function.prototype.bind = function(context){ self = this; //保存this,即調用bind方法的目標函數 return function(){ return self.apply(context,arguments); }; };
考慮到函數柯里化的狀況,咱們能夠構建一個更加健壯的bind()
:函數
Function.prototype.bind = function(context){ var args = Array.prototype.slice.call(arguments, 1), self = this; return function(){ var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); return self.apply(context,finalArgs); }; };
此次的bind()
方法能夠綁定對象,也支持在綁定的時候傳參。this
繼續,Javascript的函數還能夠做爲構造函數,那麼綁定後的函數用這種方式調用時,狀況就比較微妙了,須要涉及到原型鏈的傳遞:spa
Function.prototype.bind = function(context){ var args = Array.prototype.slice(arguments, 1), F = function(){}, self = this, bound = function(){ var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); return self.apply((this instanceof F ? this : context), finalArgs); }; F.prototype = self.prototype; bound.prototype = new F(); retrun bound; }
這是《JavaScript Web Application》一書中對bind()
的實現:經過設置一箇中轉構造函數F,使綁定後的函數與調用bind()
的函數處於同一原型鏈上,用new操做符調用綁定後的函數,返回的對象也能正常使用instanceof,所以這是最嚴謹的bind()
實現。prototype
對於爲了在瀏覽器中能支持bind()
函數,只須要對上述函數稍微修改便可:code
Function.prototype.bind = function (oThis) { if (typeof this !== "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; };