2012-06-01 20 views
11

Me gustaría usar funciones como claves en un objeto javascript. Los siguientes trabajos, al menos en Chrome:¿Las funciones son claves válidas para las propiedades de los objetos javascript?

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

¿Esto está cubierto por la norma? ¿Por qué navegadores es compatible?

+0

Bueno, trabajó en Chrome. Entonces podría funcionar en Safari y Firefox –

+0

, creo que es como si alertaras una función, de alguna manera el motor la analiza como una cadena porque es permisiva ... Pero diría que no es una buena idea, a menos que lances como cadena usted mismo antes (es posible que me pregunte) – Sebas

+0

Las claves de cualquier tipo de cualquier objeto de clase del diccionario deben tener una operación bien definida ==. Tal operación no se puede definir para las funciones (http://en.wikipedia.org/wiki/Rice%27s_theorem). –

Respuesta

14

Todo se pone entre corchetes se convierte en una cadena, y esto ocurre incluso si se pone una función, una fecha, una expresión regular ... Así que, en realidad estás creando un objeto como éste:

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

Este es un comportamiento predeterminado, también funciona en IE si te lo preguntabas. En realidad fue explotado por John Resig en su famous addEvent function.

+2

Tenga en cuenta que las funciones con cierres diferentes se pueden convertir a la misma cadena y acceder a la misma propiedad. Desde la consola del nodo: > var maker = function (a) {return function() {console.log (a); }; }; > var bb = fabricante ('BB') > bb() bb > var cc = fabricante ('dd') > cc() dd > test var = {}; > test [bb] 'AA' = > test 'AA' [bb] 'AA' > bb() bb > test { 'function() {console.log (a); } ':' AA '} > test [cc] =' DD ' ' DD ' > test {' function() {console.log (a); } ':' DD '} > prueba [bb] ' DD ' > prueba [cc] ' DD ' – JoeAndrieu

4

ECMAScript 5.1 - Sección 11.2.1:

La producción MemberExpression : MemberExpression [ Expression ] se evalúa de la siguiente manera:

  1. Vamos baseReference ser el resultado de evaluar MemberExpression.
  2. Deje que baseValue sea GetValue (referencia base).
  3. Deje que propertyNameReference sea el resultado de evaluar Expression.
  4. Deje que propertyNameValue sea GetValue (propertyNameReference).
  5. Llamada CheckObjectCoercible (baseValue).
  6. Deje que propertyNameString sea ToString (propertyNameValue).
  7. Si la producción sintáctica que se está evaluando está contenida en el código de modo estricto, deje que strict sea cierto, de lo contrario, deje strict sea falso.
  8. Devuelve un valor de tipo Referencia cuyo valor base es Valor base y cuyo nombre de referencia es propertyNameString y cuyo indicador de modo estricto es estricto.

Así que cuando se utiliza obj[whatever], whatever se convierte en una cadena. Para una función, esta será una cadena que contiene el código fuente de la función.

Ejemplo:

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 
}) 
Cuestiones relacionadas