2011-06-16 30 views
15

在Mozilla開發人員中心,有一個關於Function.prototype.bind函數的頁面,併爲不支持此功能的瀏覽器提供兼容性功能。使用'instanceof function(){}'的原因?

但是,當分析此兼容性代碼時,我找不到爲什麼他們使用instanceof nopnop已被設置爲function() {}。這與bind ECMA規範的哪一部分相符?哪些變量是function() {}的實例?

以下返回false,所以我不完全知道它用於什麼。在做​​檢查時,什麼事情返回true?

(function() {}) instanceof (function() {}) // false 

的代碼如下:

Function.prototype.bind = function(obj) { 
    if(typeof this !== 'function') 
     throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 

    var slice = [].slice, 
     args = slice.call(arguments, 1), 
     self = this, 
     nop = function() {}, 
     bound = function() { 
      return self.apply(this instanceof nop ? this : (obj || {}), 
           args.concat(slice.call(arguments)));  
     }; 

    bound.prototype = this.prototype; 

    return bound; 
}; 

回答

8

有人編輯了,使得它有用的部分。下面是它曾經是什麼樣子:

Function.prototype.bind = function(obj) { 
    var slice = [].slice, 
    args = slice.call(arguments, 1), 
    self = this, 
    nop = function() {}, 
    bound = function() { 
     return self.apply(this instanceof nop ? this : (obj || {}), 
          args.concat(slice.call(arguments)));  
    }; 

    // These lines are the important part 
    nop.prototype = self.prototype; 
    bound.prototype = new nop(); 

    return bound; 
}; 

我回答另一個問題是問同樣的事情(但是當代碼是正確的)位置:mozilla's bind function question

的原因this instanceof nop檢查是這樣,如果你調用綁定功能作爲構造(即與new運營商),this被綁定到新的對象,而不是不管你傳遞給bind

來解釋「重要組成部分」,nop基本上得到插入的原型鏈中,這樣當你調用函數的構造,thisnop一個實例。

所以,如果你運行var bound = original.bind(someObject);原型鏈將是這樣的:

 
    original 
    | 
    nop 
    | 
    bound 

我爲什麼他們用nop代替this instanceof self的猜測是,這樣的綁定功能,將有它自己的prototype財產(即從繼承self's)。這可能不是因爲這可能是它被部分編輯出來的原因。無論如何,現在的代碼是不正確的,但只要你不使用該函數作爲構造函數就會工作。

3

似乎有要與實現一個錯誤。 nop永遠不會用於(實例化任何東西)期待那0123'檢查,這對於任何事情來說永遠不會是真的,因爲沒有任何對象可以從nop實例化,它被深埋在那個閉包中。

考慮一下:

// Identical definition, but different Function instances 
var nop = function() {}, 
    mop = function() {}; 

var obj1 = new mop; 

obj1 instanceof mop // true 
obj1 instanceof nop // false