Элементы дерева 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
и сопутствующий ему чертов раздражающий синтаксис рококо... (...)