Javascript命名函数表达式,参考错误

问题描述:

我使用以下代码非常随机地(大约一次在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

这是因为存在于某些浏览器版本中的命名函数表达式的实现中的一个错误。

在这些浏览器中,使用命名函数表达式时会创建两个独立的函数对象。属性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