bind()實現

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;
  };
相關文章
相關標籤/搜索