Элементы дерева DOM с идентификаторами становятся глобальными переменными?

Работая над идеей для простой оболочки HTMLElement, я наткнулся на следующее: Internet Explorer и Chrome:

Для данного элемента HTMLElement с идентификатором в дереве DOM можно получить div, используя его идентификатор в качестве имени переменной. Итак, для div как

<div id="example">some text</div>

в Internet Explorer 8 и Chrome вы можете сделать:

alert(example.innerHTML); //=> 'some text'

или

alert(window['example'].innerHTML); //=> 'some text'

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

Ответ 1

Что должно произойти, так это то, что 'именованные элементы добавляются как кажущиеся свойства объекта document. Это действительно плохая идея, так как позволяет именам элементов сталкиваться с реальными свойствами document.

IE ухудшил ситуацию, добавив именованные элементы в качестве свойств объекта window. Это вдвойне плохо, потому что теперь вам нужно избегать именования ваших элементов после того, как захотите использовать какой-либо из членов объекта document или window (или любого другого библиотечного кода в вашем проекте).

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

Обычно считается, что плохая практика опускать var, а также полагаться на именованные элементы, которые видны на window или как глобальные. Придерживайтесь document.getElementById, который более широко поддерживается и менее двусмыслен. Вы можете написать тривиальную функцию обертки с более коротким именем, если вам не нравится ввод текста. В любом случае, нет смысла использовать кеш-поиск с идентификатором-элементом, поскольку браузеры обычно оптимизируют вызов getElementById, чтобы использовать быстрый поиск; все, что вы получаете, это проблемы, когда элементы меняются id или добавляются/удаляются из документа.

Opera скопировала IE, а затем присоединилась WebKit, и теперь как ранее нестандартная практика размещения именованных элементов в свойствах document, так и ранее IE-только практика размещения их на window являющийся стандартизированным HTML5, чей подход заключается в том, чтобы документировать и стандартизировать каждую ужасную практику, причиненную на нас авторами браузеров, делая их частью сети навсегда. Таким образом, Firefox 4 также будет поддерживать это.

Что такое "именованные элементы"? Все, что связано с id, и все, что используется name для целей идентификации: то есть формы, изображения, привязки и несколько других, но не другие несвязанные экземпляры атрибута name, такие как имена управления в поля ввода формы, имена параметров в <param> или тип метаданных в <meta>. "Идентификация name - это те, которые следует избегать в пользу id.

Ответ 2

Как упоминалось в предыдущем ответе, это поведение называется именованным доступом к объекту окна. Значение атрибута name для некоторых элементов и значение атрибута id для всех элементов становятся доступными в качестве свойств объекта глобального window. Они известны как именованные элементы. Поскольку window является глобальным объектом в браузере, каждый именованный элемент будет доступен как глобальная переменная.

Первоначально он был добавлен Internet Explorer и в конечном итоге был реализован всеми другими браузерами просто для совместимости с сайтами, которые зависят от этого поведения. Интересно, что Gecko (движок рендеринга Firefox) решил реализовать это только в режиме причуд, тогда как другие движки рендеринга оставили его включенным в стандартном режиме.

Однако, начиная с Firefox 14, Firefox теперь поддерживает именованный доступ к объекту window в стандартном режиме. Почему они изменили это? Оказывается, еще много сайтов, которые полагаются на эту функциональность в стандартном режиме. Microsoft даже выпустила маркетинговую демоверсию, которая не позволила демоверсии работать в Firefox.

В последнее время Webkit рассмотрел обратное: переводить именованный доступ к объекту window в режим причуд. Они решили против этого по той же причине, что и Геккон.

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

Зачем? В этой статье можно подвести итог многим рассуждениям о том, почему глобальные переменные плохие. Проще говоря, наличие множества дополнительных глобальных переменных приводит к большему количеству ошибок. Допустим, вы случайно набрали имя var и случайно набрали id узла DOM, СЮРПРИЗ!

Кроме того, несмотря на стандартизацию, в реализациях браузеров именованного доступа все еще остается довольно много несоответствий.

  • IE неправильно делает значение атрибута name доступным для элементов формы (input, select и т.д.).
  • Gecko и Webkit неправильно НЕ делают теги <a> доступными через атрибут name.
  • Gecko неправильно обрабатывает несколько именованных элементов с одинаковыми именами (вместо массива ссылок возвращает ссылку на один узел).

И я уверен, что есть еще, если вы попытаетесь использовать именованный доступ в крайних случаях.

Как упоминалось в других ответах, используйте document.getElementById чтобы получить ссылку на узел DOM по его id. Если вам нужно получить ссылку на узел по его атрибуту name используйте document.querySelectorAll.

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

Если вам интересно, я расскажу об этом более подробно в моем блоге - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/.

Ответ 3

В этих случаях вы должны придерживаться getElementById(), например:

document.getElementById('example').innerHTML

IE любит смешивать элементы с атрибутами name и ID в глобальном пространстве имен, поэтому лучше всего указать, что вы пытаетесь получить.

Ответ 4

Да, они делают.

Протестировано в Chrome 55, Firefox 50, IE 11, IE Edge 14 и Safari 10
в следующем примере:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <div id="im_not_particularly_happy_with_that">
    Hello World!
  </div>
  <script>
    im_not_particularly_happy_with_that.innerText = 'Hello Internet!';
  </script>
  <!-- Looking at you W3 HTML5 spec group ಠ_ಠ -->
</body>
</html>

http://jsbin.com/mahobinopa/edit?html,output

Ответ 5

Должен звучать вопрос: "Становятся ли HTML-теги с предоставленными идентификаторами глобально доступными элементами DOM?"

Ответ ДА!

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

Тем не менее, Netscape Mozilla отказалась отвечать (их вторгаясь) W и упорно продолжали использовать устаревшую атрибут Имени, чтобы создать хаос и, следовательно, разорвут функциональность сценариев и удобство кодирования приносимого W3C введения уникальных идентификаторов.

После фиаско Netscape Navigator 4.7 все их разработчики пошли и проникли в W3C, в то время как их партнеры вытесняли Интернет с неправильной практикой и неправильно использовали примеры. Принудительное использование и повторное использование уже устаревшего атрибута Name [!, Который не должен был быть уникальным] наравне с атрибутами ID, чтобы сценарии, использующие идентификаторы для доступа к определенным элементам DOM, просто ломались!

И сломайте их, как они бы также писали и публиковали обширные уроки и примеры кодирования [их браузер не распознал бы в любом случае], такие как document.all.ElementID.property вместо ElementID.property чтобы по крайней мере сделать его неэффективным и дать браузеру больше накладных расходов в случае, если он не просто сломал его в домене HTML, используя тот же токен для (теперь [1996-97], устаревший) имени и стандартный атрибут ID, предоставляющий ему то же значение токена.

Им легко удалось убедить - тогда - подавляющую армию невежественных любителей написания кода в том, что имена и идентификаторы практически одинаковы, за исключением того, что атрибут идентификатора короче и, следовательно, сохраняет байты и более удобен для кодера, чем свойство древнего имени. Что, конечно, было ложью. Или - в их заменяющих опубликованных статьях HTML, убедительных статьях о том, что вам нужно будет указывать и имя, и идентификатор для своих тегов, чтобы они были доступны для механизма сценариев.

Убийцы Мозаики [под кодовым названием "Мозилла"] были настолько взбешены, что подумали: "Если мы пойдем вниз, то и Интернет тоже".

Растущая Microsoft - с другой стороны - была настолько наивна, что подумала, что должна оставить устаревшее и помеченное для удаления свойство Name и обращаться с ним так, как если бы это был идентификатор с уникальным идентификатором, чтобы они не нарушали функциональные возможности сценариев. старые страницы, закодированные стажерами Netscape. Они были смертельно неправы...

И возвращение коллекции массивов элементов, конфликтующих с ID, также не было решением этой умышленной искусственной проблемы. На самом деле это победило всю цель.

И это единственная причина, по которой W3C стал ужасным и дал нам такие идиотские черты, как document.getElementById и сопутствующий ему чертов раздражающий синтаксис рококо... (...)