Почему бы нам просто не использовать идентификаторы элементов в качестве идентификаторов в JavaScript?

Все браузеры, с которыми я пришел работать, позволяют получить доступ к элементу с помощью id="myDiv", просто написав:

myDiv

Смотрите здесь: http://jsfiddle.net/L91q54Lt/

Во всяком случае, этот метод, как представляется, довольно плохо документирован, и на самом деле источники, с которыми я сталкиваюсь, даже не упоминают об этом, а вместо этого предполагают, что использовать

document.getElementById("myDiv")

или, возможно,

document.querySelector("#myDiv")

для доступа к элементу DOM, даже если его идентификатор известен заранее (т.е. не вычисляется во время выполнения). Я могу сказать, что последние подходы имеют преимущество в обеспечении безопасности кода, если кто-то непреднамеренно пытается переопределить myDiv в более широкой области (не такая блестящая идея, хотя...), перезаписывает ее с каким-то другим значением и продолжается без заметив столкновение.

Но что это? Есть ли проблемы в использовании короткой формы, отличной от кода, или чего еще я здесь не вижу?

Ответ 1

Во всяком случае, этот метод, похоже, довольно плохо документирован, и на самом деле источники, с которыми я сталкиваюсь, даже не упоминают [...]

Опора на неявно объявленные глобальные переменные в сторону, отсутствие документации - отличная причина не использовать ее.

Явное продвижение значений id в глобальные переменные не соответствует стандартам (спецификация HTML5 для атрибута ID не упоминает об этом) и, следовательно, вы не должны предполагать, что будущие браузеры его реализуют.

EDIT: Оказывается, это поведение соответствует стандартам. В HTML5 window должен поддерживать доступ к свойствам "Именованные элементы":

Именованные объекты с именем name для целей вышеуказанного алгоритма - это те, которые:

  • дочерние контексты просмотра активного документа, имя которого - имя,
  • a, апплет, область, вставка, форма, frameset, img или элементы объекта, которые имеют атрибут содержимого имени, значение которого является именем, или
  • HTML-элементы, у которых есть атрибут содержимого id, значение которого является именем.

Источник: Спецификация HTML 5, "Именованный доступ к объекту окна" , акцент мой.

Исходя из этого, соблюдение стандартов не является основанием для предотвращения этого шаблона. Однако сама спецификация не рекомендует использовать ее:

Как правило, полагаясь на это, вы получите хрупкий код. Который Идентификация конечного отображения в этот API может меняться со временем, поскольку новые функции например, к веб-платформе. Вместо этого используйте document.getElementById() или document.querySelector().

Ответ 2

Отличный вопрос. Как, вероятно, Эйнштейн не сказал, все должно быть как можно проще и проще.

последние подходы имеют преимущество, заключающееся в том, чтобы держать код в безопасности, если кто-то непреднамеренно пытается переопределить myDiv в более широкой области (не такая блестящая идея, хотя...), перезаписывает ее с некоторым разным значением и продолжается, не замечая столкновения

Это главная причина, почему это плохая идея, и ее достаточно. Надежные глобальные переменные. Они могут быть перезаписаны в любое время любым script, который заканчивается на странице.

В дополнение к этому просто ввод текста myDiv не является "короткой формой" document.getElementById(). Его ссылка на глобальную переменную. document.getElementById() будет с радостью возвращать null, если элемент не существует, в то время как попытка получить доступ к несуществующей глобальной переменной вызовет ошибку ссылки, поэтому вам необходимо обернуть ссылки на глобальные блок try/catch будет безопасным.

Это одна из причин, почему jQuery настолько популярен: если вы делаете $("#myDiv").remove(), и нет элемента с идентификатором myDiv, ошибка не будет выдана - код просто молчат ничего, что часто именно то, что вы хотите, когда выполняете манипуляции с DOM.

Ответ 3

Есть несколько причин:

Вы не хотите, чтобы ваш код и разметка были связаны.

Используя определенный вызов для доступа к div, вам не нужно беспокоиться о повреждении глобального пространства. Добавьте библиотеку, которая объявляет myDiv в глобальном пространстве, и вы окажетесь в мире боли, который будет трудно исправить.

Вы можете получить доступ к элементам по идентификатору, которые не являются частью DOM

Они могут быть фрагментом, фреймом или элементом, который был отсоединен и еще не присоединен к DOM.

РЕДАКТИРОВАТЬ: Пример доступа к неприкрепленным элементам по ID

var frag = document.createDocumentFragment();
var span = document.createElement("span");
span.id = "span-test";
frag.appendChild(span);
var span2 = frag.getElementById("span-test");
alert(span === span2);

Ответ 4

В моем случае у меня был iframe внутри моей страницы. Меня смутил атрибут id против атрибута name, оба из которых влияли на переменную с именем inner_iframe, доступную из window !

  • Если бы я использовал только атрибут id, например id="inner_iframe", window.inner_iframe - это HTMLIFrameElement. Свойства включают inner_iframe.contentDocument и inner_iframe.contentWindow как описано здесь *

    • В этом случае я предполагаю, что переменная появляется в window по причине, указанной @joew в принятом ответе:

      HTML-элементы, имеющие атрибут содержимого id, значением которого является name

  • Если бы я использовал только атрибут name, например name="inner_iframe" то window.inner_iframe - это "рамка", или "объект окна". contentWindow, поэтому атрибут name inner_iframe не имеет свойств contentDocument или contentWindow.

    • Я предполагаю, что переменная inner_iframe появляется в window по причине, указанной @joew в принятом ответе

      дочерние контексты просмотра активного документа, имя которого name

  • Если я использовал оба name и id признаки, и я дал оба атрибута такое же значение name="inner_iframe" id="inner-iframe"; атрибут name превзошел/заточил атрибут id; У меня остался "объект окна", а не HTMLIFrameElement !

Поэтому я хочу быть осторожным с двусмысленностью; конфликт между атрибутами name и id в одном и том же объекте с двумя разными API: это просто особый случай, когда неявное поведение и привязка к переменной окна могут сбить вас с толку.

* (и только если <script> был загружен после/ниже <iframe> в HTML, или <script> ждал до window.onload прежде чем пытаться получить доступ по атрибуту id)

** это отличие "фрейма" от элемента DOM описано в документации Mozilla как:

Каждый элемент в псевдомассиве window.frames представляет объект окна, соответствующий заданному элементу или содержимому, а не элемент DOM кадра (i) (т.е. Window.frames [0] - это то же самое, что document.getElementsByTagName("iframe") ) [0].contentWindow).