Становятся ли элементы дерева DOM с идентификаторами глобальными переменными? - PullRequest
334 голосов
/ 08 августа 2010

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

Для заданного HTMLE-элемента с идентификатором в дереве 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?

Ответы [ 5 ]

373 голосов
/ 08 августа 2010

Предполагается, что «именованные элементы» добавляются в качестве очевидных свойств объекта 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, такие как control- имена в полях ввода формы, имена параметров в <param> или тип метаданных в <meta>. «Идентификация» name - это те, которых следует избегать в пользу id.

47 голосов
/ 27 июля 2012

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

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

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

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

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

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

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

  • IE неправильно делает значение атрибута name доступным для элементов формы (ввод, выбор и т. д.).
  • 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/.

20 голосов
/ 08 августа 2010

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

document.getElementById('example').innerHTML

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

3 голосов
/ 23 декабря 2016

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

Протестировано в 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

2 голосов
/ 06 февраля 2019

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

Ответ - ДА!

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

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

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...