模擬實現相容低版本IE瀏覽器的原生bind()

admin發表於2017-12-04

關於javascript的bind()基本功能可以參閱javascript bind()一章節。

但是此函式是在IE8和IE8以下瀏覽器中並不支援,下面就介紹一下如何模擬實現此功能。

程式碼如下:

[JavaScript] 純文字檢視 複製程式碼
if(!Function.prototype.bind){
  Function.prototype.bind=function(oThis){
    if (typeof this !== 'function'){
      throw new TypeError('呼叫者不是當前函式物件');
    }
 
    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;
  };
}

上面的程式碼實現了相容效果,下面介紹一下它的實現過程。

一.程式碼註釋:

1.if(!Function.prototype.bind),判斷當前瀏覽器是否支援bind()函式。

2.Function.prototype.bind=function(oThis){},如果不支援的話,就新增一個bind函式,引數自然是this要指向的物件。

3.if (typeof this !== 'function'){

  throw new TypeError('呼叫者不是當前函式物件');

},因為使用call或者apply等方式的存在,可以將呼叫者轉換成其他物件,比如func.bind.call(obj),就是為了防止此情況的出現。

4.var aArgs = Array.prototype.slice.call(arguments, 1),獲取為bind函式傳遞的從第二個開始以後的引數。

5.fToBind = this,將當前函式物件的this引用賦值給變數fToBind 。

6.fNOP = function() {},使用表示式方式建立一個函式,它的用法在後面介紹。

7.fBound = function() {  

  return fToBind.apply(this instanceof fNOP && oThis ? this : oThis||window , 

  aArgs.concat(Array.prototype.slice.call(arguments)));

},fBound函式就是要返回的函式。return fToBind.apply()前面加上return是因為fToBind函式可能會有返回值。

this instanceof fNOP && oThis ? this : oThis||window,this instanceof fNOP可以判斷是否用作建構函式,至於&&與運算子後面的oThis 是否需要值得商榷,如果按照MDN的原始碼的話,當用作建構函式不傳遞oThis引數的時候,那麼會用window物件呼叫fToBind函式,如果此位置沒有oThis,那麼無論是否bind()函式傳遞oThis引數,函式fBound用作建構函式的時候,都能夠使用this呼叫fToBind()函式。

aArgs.concat(Array.prototype.slice.call(arguments)),兩個陣列進行連線,最終結果就是要傳遞給fToBind()函式的引數。

8.fNOP.prototype = this.prototype,此句感覺完全沒有必要,可能是為了增加原型鏈的密度。

9.fBound.prototype = new fNOP(),將fBound的原型物件設定為fNOP()的例項物件,這樣的話如果fBound 用作建構函式的話,this instanceof fNOP返回值為true。

10.return fBound,返回此函式。

二.相關閱讀:

1.typeof運算子的用法參閱javascript typeof一章節。

2.slice()方法參閱javascript slice()一章節。

3.call()方法可以參閱javascript call()一章節。

4.concat()函式可以參閱js陣列 concat()一章節。

5.prototype原型可以參閱javascript prototype原型一章節。

相關文章