Можете Вы объяснять как выражение JavaScript:
[1 [{}]]
анализирует/оценивает? В Firefox, Chrome, Konqueror и носороге, это, кажется, создает массив с единственным элементом, undefined
. Однако я не понимаю почему.
В Firefox:
[1 [{}]].toSource()
производит
[(void 0)]
Замена 1 с другими значениями JavaScript, кажется, приводит к тому же результату.
Обновление: Я думаю, что понимаю теперь. codeka, Adrian и CMS разъяснили вещи. До стандарта я пытался идти через ECMAScript 5.
1 [{}]
Средство доступа Свойства, таким образом, оно покрыто §11.2.1.baseReference
результат оценки 1
, так все еще 1
.baseValue = GetValue(baseReference) == 1
.GetValue
(§8.7.1), Type(1)
не Reference
(разрешенная привязка имени), так возвратитесь 1.propertyNameReference
результат оценки {}
, так пустой объект.propertyNameValue = GetValue(propertyNameReference) == {}
CheckObjectCoercible(baseValue)
(§9.10), мы возвращаемся (Число объектно-принудительно).propertyNameString = ToString(propertyNameValue)
ToString
(§9.8), возвратиться ToString(ToPrimitive({}, hint String))
ToPrimitive
(§9.1), возвратите результат объекта [[DefaultValue]]
, передача PreferredType
(строка).[[DefaultValue]]
(§8.12.8), позвольте toString быть результатом [[Get]]
с аргументом toString
."[object " + [[Class]] + "]"
, где [[Class]]
"Объект" для объектного прототипа по умолчанию. toString
, мы называем его с аргументом this
быть {}
.Reference
, чье основное значение BaseValue
(1) и чье имя, на которое ссылаются, propertyNameString
("[object Object]"
).Мы затем идем, чтобы Выстроить инициализатор (§11.1.4) и создать единственный массив элемента с результатом.
Если мы немного разобьем его, то увидим:
var foo = 1;
var bar = {};
var baz = foo[bar];
[baz];
Я считаю, что это валидный JavaScript, но я не эксперт...
Читая комментарии OP и Nick, я думаю, что могу немного расширить ответ Адриана, чтобы сделать его более ясным.
Это совершенно правильный JavaScript.
JavaScript обрабатывает имена свойств объектов как строки, объекты не могут содержать другие типы или другие объекты как ключи, это просто строки.
Нотация скобок property accessor (MemberExpression [ Expression ]
) неявно преобразует выражение между скобками в строку, так:
var obj = {};
obj[{}] = "foo";
alert(obj["[object Object]"]); // foo
В примере выше видно, что я присваиваю значение свойству {}
, а {}. toString()
(или {}+''
) выдает строку "[объект Object]
(через Object.prototype.toString
).
Выражение 1 [{}]
неявно преобразует примитив 1 Number
в объект (это делает аксессор property) и ищет свойство "[object Object]"
поиск свойства производится по Number. prototype
и Object.prototype
объектах, например:
1['toString'] === Number.prototype.toString; // true
Наконец, выражение 1 [{}]
само заключено в скобки ([1 [{}]]
), это фактически литерал массива.
В заключение вот как парсер оценивает выражение:
[1 [{}]];
// ^ The accessor expression is evaluated and converted to string
[1 ["[object Object]"]];
// ^ A property lookup is made on an Number object
// trying to access a property named "[object Object]"
[undefined];
// ^ the property is obviously not found
[undefined];
//^ ^
// An array literal is created with an element `0` which its value is `undefined`
Это потому, что вы пытаетесь получить свойство {}
объекта 1
и затем поместить его в массив. 1
не имеет свойства {}
, поэтому 1[{}]
является undefined
.
Если вы замените 1
на массив, вы увидите, как это работает. С 1
в качестве [5]
и {}
в качестве 0
, получается [[5][0]]
.
Также следует помнить, что obj['property']
- это то же самое, что obj.property
.