В JavaScript, как объект obj, который не имеет свойства с именем "foo", может дать значение с помощью obj ["foo"]?

Я прочитал в книге "Секреты JavaScript-ниндзя", что мы можем использовать document.all["id"] чтобы получить все элементы в документе с таким ID, если браузер поддерживает его. (хотя предположительно мы должны иметь только один элемент с определенным ID).

Но document.all возвращает объект HTMLAllCollection, и я вижу в Chrome, что у него есть 9 элементов, например массив (9 элементов, как установлено в jsfiddle). Поэтому я могу понять, почему document.all[9] может вернуть элемент, но почему document.all["foo"] возвращает его тоже? Если мы определим var obj = { foo: 123 }, то мы можем сказать obj["foo"], но document.all не является объектом с ключом foo. Так что, предположим, document.all["foo"] не сможет вернуть такой элемент.

Примечание. Этот вопрос заключается не в том, чтобы спросить об использовании document.all, и не о том, чтобы просить иметь два элемента с одинаковым идентификатором на странице.Он спрашивает, почему объект obj, который, похоже, не имеет ключа foo, может дать значение с помощью obj["foo"] Я не знаю, почему это неверный вопрос программирования.

образец кода:

1 элемент с таким ID: http://jsfiddle.net/ArR5x/5/

2 элемента с таким ID: http://jsfiddle.net/ArR5x/10/

Обновление: Дэн Тао прав.Это связано с тем, что некоторые свойства перечислимы, а некоторые нет, и мы можем легко создать ту же ситуацию, если поддерживается ECMAScript 5: http://jsfiddle.net/Akdp9/12/. Действительный вопрос о JavaScript и реальный ответ заключается в том, что это связано с перечислимым атрибутом свойства.

3 ответа

Кажется, я понимаю, почему вы в замешательстве. Позвольте мне объяснить пару вещей, чтобы устранить любую путаницу. Некоторые из этого вы, возможно, уже знаете, но я собираюсь охватить все это, чтобы быть в безопасности.

Во-первых, объект, подобный массиву, может по-прежнему иметь свойства, подобные любому другому объекту. Даже ванильный Array подобен этому.

var arr = [1, 2, 3];
arr.foo = "bar";
arr["foo"]; // => "bar"

Поэтому представляется вполне разумным, что после разбора DOM браузер заполняет document.all со свойствами, соответствующими каждому ID на странице, хотя HTMLAllCollection скорее подобен массиву.

Во-вторых, свойства объекта не обязательно все создаются равными. Возможно, вы пробовали это и заметили отсутствие какого-либо свойства "foo":

Object.keys(document.all)
// => ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "length"]

Однако "foo" действительно является свойством document.all. Вы можете проверить это довольно легко:

document.all.foo;
// => [<div id="​" foo""="">​hello​</div>​, <div id="​" foo""="">​world​</div>​]

document.all.hasOwnProperty("foo") // => true

Проблема здесь в том, что это не перечислимое свойство. Это означает, что он не будет отображаться in цикле for/in, а также объясняет, почему вы не видите его, когда все Object.keys.

Вы можете подтвердить это с помощью метода propertyIsEnumerable:

document.all.propertyIsEnumerable("foo"); // => false

Поэтому, в конце концов, это не столько загадка. Произвольные свойства могут быть назначены объекту document.all, как они могут с массивами. И это имеет место здесь; свойства просто не перечислимы.


DOM не реализован в Javascript, и большинство правил Javascript к нему не применяются.

Например, в Chrome !!document.all оценивает значение false хотя в правилах Javascript все объекты являются правдивыми.


Просто потому, что вы не должны иметь несколько элементов с одинаковым идентификатором, это не означает, что вы не можете их запросить. Селектор CSS будет применяться к нескольким элементам с тем же идентификатором, что и querySelectorAll:

document.querySelectorAll('#foo');

также может возвращать несколько элементов.

Вот скрипка, чтобы доказать это: http://jsfiddle.net/EgBbN/

licensed under cc by-sa 3.0 with attribution.