2012-06-01 31 views
11

我想使用函数作为JavaScript对象中的键。以下作品,至少在Chrome中:JavaScript对象属性的函数是否有效的键?

var registry = {}; 
function Foo(){ }; 
function Bar(){ }; 
registry[Foo] = 42; 
registry[Bar] = 43; 
alert(registry[Foo] + " < " + registry[Bar]); 

这是标准所涵盖的吗?它支持哪些浏览器?你方括号把

+0

好,曾在Chrome中。所以它可能在Safari和Firefox中工作 –

+0

我认为它就像你警告一个函数,不知何故引擎将它解析为一个字符串,因为它是宽容的......但我认为这不是一个好主意,除非你施放它作为一个字符串你自己以前(是这样的事情可能我不知道) – Sebas

+0

任何类型的任何字典类对象的键必须有一个定义良好的==操作。无法为函数定义这样的操作(http://en.wikipedia.org/wiki/Rice%27s_theorem)。 –

回答

14

一切都转换成字符串,而出现这种情况,即使你把一个函数,日期,正则表达式...所以在那里,你实际上是创建这样一个对象:

var registry = { 
    "function Foo(){ }" : 42, 
    "function Bar(){ }" : 43 
}; 

这是一个默认行为,它在IE工作太多,如果你想知道。它实际上是由John Resig在他的famous addEvent function中利用的。

+2

请注意,具有不同闭包的函数可以转换为相同的字符串,并访问相同的属性。 从节点控制台: > var maker = function(a){return function(){console.log(a); }; }; > VAR BB =制造商( 'BB') > BB() BB >变种CC =制造商( 'DD') > CC() DD >变种测试= {}; >测试[BB] = 'AA' 'AA' >测试[BB] 'AA' > BB() BB >测试 {“函数(){的console.log(a)的}':'AA'} > test [cc] ='DD' 'DD' > test {'function(){console.log(a);' 'DD'} > test [bb] 'DD' > test [cc] 'DD' – JoeAndrieu

4

的ECMAScript 5.1 - 第11.2.1节:

生产MemberExpression : MemberExpression [ Expression ]被评价为如下:

  1. 让baseReference是评估MemberExpression的结果。
  2. 让baseValue成为GetValue(baseReference)。
  3. 让propertyNameReference是评估Expression的结果。
  4. 让propertyNameValue为GetValue(propertyNameReference)。
  5. 调用CheckObjectCoercible(baseValue)。
  6. 让propertyNameString是的ToString(propertyNameValue)。
  7. 如果正在评估包含在严格模式代码语法生产,让严格的是真实的,否则让 严格是假的。
  8. 返回其基值是基值和其中引用的名字是 propertyNameString,并且其严格模式标志是严格的类型参考的值。

因此,在使用时obj[whatever]whatever被转换为字符串。对于函数,这将是一个包含函数源代码的字符串。

例子:

js> var func = function() { return 'hi'; }; 
js> function helloworld() { return 'hello world'; } 
js> var obj = {}; 
js> obj[func] = 123; 
js> obj[helloworld] = 456; 
js> obj 
({'function() {\n return "hi";\n}':123, 
    'function helloworld() {\n return "hello world";\n}':456 
}) 
相关问题