Являются ли функции действительными ключами для свойств объекта javascript?

Я хотел бы использовать функции как ключи в объекте javascript. Следующие работы, по крайней мере, в Chrome:

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

Это покрывается стандартом? По каким браузерам он поддерживается?

Ответ 1

Все, что вы помещаете между квадратными скобками, преобразуется в строку, и это происходит, даже если вы добавляете функцию, дату, регулярное выражение... Итак, вы на самом деле создаете такой объект:

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

Это поведение по умолчанию, оно работает и в IE, если вам интересно. Фактически он был использован Джоном Ресигом в известной функции addEvent.

Ответ 2

ECMAScript 5.1 - Раздел 11.2.1:

Произведение MemberExpression : MemberExpression [ Expression ] оценивается следующим образом:

  • Пусть baseReference будет результатом оценки MemberExpression.
  • Пусть baseValue будет GetValue (baseReference).
  • Пусть свойствоNameReference является результатом вычисления выражения.
  • Пусть свойствоNameValue будет GetValue (propertyNameReference).
  • Вызов CheckObjectCoercible (baseValue).
  • Пусть свойствоNameString - ToString (propertyNameValue).
  • Если синтаксическое производство, которое оценивается, содержится в коде строгого режима, пусть строгое истинно, иначе пусть  строго быть ложным.
  • Возвращает значение типа Reference, базовое значение которого является базовым значением, а ссылочное имя - 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
})