2014-08-29 44 views
0

我使用以下代碼非常隨機地(大約一次在200次嘗試中)收到「參考錯誤」。Javascript命名函數表達式,參考錯誤

var securityPrototype = { 
    init: function(){ /* ... */ }, 
    encryptionKey: function x() { 
     var i = x.identifier; 
     return getKey(i); 
    } 
} 

securityPrototype.encryptionKey.identifier = Date.now(); 

function Security(){} 

Security.prototype = securityPrototype; 
Security.constructor = Security; 

function getKey(){ /* ... */ } 

var gate = new Security() 
gate.encryptionKey(); // Randomly throws : ReferenceError: x is not defined 

該代碼段位於其他代碼中,但沒有使用「eval」,也沒有使用'with'運算符。

我想弄清楚是否由於任何情況可能在這裏得到這個錯誤。

重現此操作的瀏覽器:Mac和Windows上的Chrome。 IE和Safari工作正常。

+2

最有可能'Math.random'是你的問題,因爲你得到的錯誤「隨機」。是否允許'Math.random'的所有​​值? – Afsa 2014-08-29 19:30:25

+0

如果是這樣,我們會得到一個不同的錯誤。其實這是可以替代的,因爲我試圖抽象函數。 – sbr 2014-08-29 19:35:50

+0

你得到錯誤的時間與沒有的時間必須有所不同。將'securityPrototype.encryptionKey.identifier'設置爲固定值,看看是否仍然出現錯誤。 – Afsa 2014-08-29 19:42:12

回答

1

這是因爲存在於某些瀏覽器版本中的命名函數表達式的實現中的一個錯誤。

在這些瀏覽器中,使用命名函數表達式時會創建兩個獨立的函數對象。屬性gate.encryptionKey是對一個功能對象的引用,而名稱x是對不同的函數對象的引用。它們都包含相同的代碼,但它們是Function類的不同實例。

當您爲gate.encryptionKey.identifier賦值時,該屬性僅在gate.encryptionKey引用的函數對象中可用。 x引用的函數對象不具有該屬性。在這些瀏覽器的行爲

簡單的例子:

var f = function g(){}; 
f === g; // false 

f.expando = 'foo'; 
g.expando; // undefined 

這個例子(例如3#)從頁Named function expressions demystified,在那裏你可以閱讀更多關於命名的函數表達式,並實現錯誤拍攝。

+0

由於'g'未在g的定義範圍之外定義,因此此代碼將給出引用錯誤。 – sbr 2014-08-29 20:05:00

+0

var f = function g(){ \t \t console.log(g === f); \t }; f()//返回true – sbr 2014-08-29 20:06:25

+0

@sbr:是的,在正確實現指定函數表達式的瀏覽器中,在函數外部使用'g'應該給出一個引用錯誤。沒有正確實現它的瀏覽器通常也存在標識符泄漏超出函數範圍的錯誤。請參閱我鏈接到的頁面上的示例#1。 – Guffa 2014-08-29 20:16:03