web-dev-qa-db-fra.com

Les éléments d'arborescence DOM avec ID sont-ils des variables globales?

Travaillant sur une idée pour un wrapper HTMLElement simple, je suis tombé sur ce qui suit pour Internet Explorer et Chrome :

Pour un HTMLElement donné avec ID dans l'arborescence DOM, il est possible de récupérer la div en utilisant son ID comme nom de variable. Donc, pour une div comme

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

dans Internet Explorer 8 et Chrome vous pouvez faire:

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

ou

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

Cela signifie-t-il que tous les éléments de l'arborescence DOM sont convertis en une variable de l'espace de noms global? Et cela signifie-t-il que l'on peut aussi utiliser cela en remplacement de la méthode getElementById dans ces navigateurs?

337
KooiInc

Ce qui est censé se produire, c’est que les ‘éléments nommés’ sont ajoutés en tant que propriétés apparentes de l’objet document. C'est une très mauvaise idée, car cela permet aux noms des éléments d'entrer en conflit avec les propriétés réelles de document.

IE a aggravé la situation en ajoutant également des éléments nommés en tant que propriétés de l'objet window. Ceci est d'autant plus grave que vous devez maintenant éviter de nommer vos éléments après un membre de l'objet document ou window que vous (ou tout autre code de bibliothèque de votre projet) voudrez peut-être utiliser. .

Cela signifie également que ces éléments sont visibles sous forme de variables globales. Heureusement, dans ce cas, toutes les déclarations var ou function globales réelles dans votre code les masquent, vous n'avez donc pas à vous inquiéter de la dénomination ici, mais si vous essayez de faire une affectation à Si vous oubliez de déclarer var une variable globale avec un nom conflictuel, vous obtiendrez une erreur dans IE lorsqu’il essaiera d’attribuer la valeur à l’élément lui-même.

Il est généralement considéré comme une mauvaise pratique d'omettre var, ainsi que de s'appuyer sur les éléments nommés visibles sur window ou sous forme de globals. S'en tenir à document.getElementById, qui est plus largement supporté et moins ambigu. Vous pouvez écrire une fonction wrapper triviale avec un nom plus court si vous n'aimez pas la frappe. Quoi qu'il en soit, il n'y a aucun intérêt à utiliser un cache de recherche id-to-element, car les navigateurs optimisent généralement l'appel getElementById pour utiliser quand même une recherche rapide; tout ce que vous avez, ce sont des problèmes lorsque des éléments changent id ou sont ajoutés/supprimés du document.

Opera a copié IE, puis WebKit a rejoint le groupe, et maintenant la pratique jusqu'alors non standardisée consistant à placer des éléments nommés sur les propriétés document, et la pratique auparavant réservée à IE à les mettre sur window sont - Beingnormalisé par HTML5, dont l’approche consiste à documenter et à normaliser toutes les terribles pratiques infligées par les auteurs de navigateur, en les intégrant à tout jamais sur le Web. Donc, Firefox 4 le supportera également.

Que sont les "éléments nommés"? Tout ce qui a un id et tout ce qui a un name est utilisé à des fins "d'identification": c'est-à-dire des formulaires, des images, des ancres et quelques autres, mais pas d'autres instances non liées d'un name attribut, comme les noms de contrôle dans les champs de saisie de formulaire, les noms de paramètre dans <param> ou type de métadonnées dans <meta>. "Identifier" names sont ceux qui devraient être évités en faveur de id.

375
bobince

Comme mentionné dans la réponse précédente, ce comportement est appelé accès nommé sur l'objet window . La valeur de l'attribut name pour certains éléments et la valeur de l'attribut id pour tous les éléments sont rendues disponibles en tant que propriétés de l'objet global window. Celles-ci sont appelées éléments nommés. Puisque window est l’objet global du navigateur, chaque élément nommé sera accessible en tant que variable globale.

Cela a été ajouté à l'origine par Internet Explorer et a finalement été mis en œuvre par tous les autres navigateurs, simplement pour assurer la compatibilité avec les sites dépendants de ce comportement. Fait intéressant, Gecko (le moteur de rendu de Firefox) a choisi de ne l'implémenter que dans mode quirks , alors que d'autres moteurs de rendu l'ont laissé en mode standard.

Cependant, à partir de Firefox 14, Firefox prend maintenant en charge l'accès nommé sur l'objet window en mode standard également. Pourquoi ont-ils changé cela? Il s'avère que de nombreux sites utilisent encore cette fonctionnalité en mode standard. Même Microsoft a publié une démo marketing qui l’a empêché de fonctionner dans Firefox.

Webkit a récemment considéré l'inverse , reléguant l'accès nommé sur l'objet window au mode quirks uniquement. Ils ont décidé de ne pas le faire selon le même raisonnement que Gecko.

Donc… fou car il semble que ce comportement soit maintenant techniquement sûr à utiliser dans la dernière version de tous les principaux navigateurs en mode standard . Mais si l'accès nommé peut sembler un peu pratique , il ne devrait pas être utilisé .

Pourquoi? Une bonne partie du raisonnement peut être résumée dans cet article à propos de pourquoi les variables globales sont mauvaises . En termes simples, avoir un tas de variables globales supplémentaires conduit à plus de bugs. Supposons que vous tapez accidentellement le nom d'un var et que vous saisissiez un id d'un nœud DOM, SURPRISE!

En outre, bien qu’il soit normalisé, il existe encore quelques divergences dans les implémentations du navigateur de l’accès nommé.

  • IE rend incorrectement la valeur de l'attribut name accessible aux éléments de formulaire (entrée, sélection, etc.).
  • Gecko et Webkit ne font PAS correctement <a> balises accessibles via leur attribut name.
  • Gecko ne gère pas correctement plusieurs éléments nommés portant le même nom (il renvoie une référence à un seul nœud au lieu d'un tableau de références).

Et je suis sûr qu'il y a plus si vous essayez d'utiliser l'accès nommé sur les cas Edge.

Comme mentionné dans d'autres réponses, utilisez document.getElementById pour obtenir une référence à un nœud DOM par son id. Si vous devez obtenir une référence à un nœud par son attribut name, utilisez document.querySelectorAll.

S'il vous plaît, veuillez ne pas propager ce problème en utilisant l'accès nommé sur votre site. Tant de développeurs Web ont perdu du temps à essayer de retrouver ce comportement magique. Nous devons vraiment agir et faire en sorte que les moteurs de rendu désactivent l’accès nommé en mode standard. À court terme, certains sites feront de mauvaises choses, mais à long terme, cela contribuera à faire progresser le Web.

Si cela vous intéresse, j'en parle plus en détail sur mon blog - https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/ =.

46
TJ VanToll

Vous devriez vous en tenir à getElementById() dans ces cas, par exemple:

document.getElementById('example').innerHTML

IE aime mélanger des éléments avec les attributs nameetID de l'espace de noms global. Il est donc préférable d'expliquer ce que vous essayez d'obtenir.

20
Nick Craver

Oui, ils le font.

Testé dans Chrome 55, Firefox 50, IE 11, IE Edge 14 et Safari 10).
avec l'exemple suivant:

<!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

3
qff

La question devrait paraître: "Les balises HTML avec les ID fournis deviennent-elles des éléments DOM accessibles de manière globale?"

La réponse est oui!

C’est ainsi que cela devait fonctionner, et c’est pourquoi le W3C a tout d’abord introduit les identifiants: L’ID d’une balise HTML dans un environnement de script analysé devient son descripteur d’élément DOM correspondant.

Cependant, Netscape Mozilla a refusé de se conformer au W3C (intrus), et il a continué à utiliser obstinément l'attribut Name (obsolète) pour créer des dégâts et donc casser la fonctionnalité de script et la commodité de codage introduite par l'introduction d'identifiants uniques par le W3C.

Après le fiasco de Netscape Navigator 4.7, leurs développeurs se sont tous infiltrés dans le W3C, alors que leurs collaborateurs remplaçaient le Web par des pratiques erronées et des exemples d'utilisation abusive. Forcer l'utilisation et la réutilisation de l'attribut Name déjà déprécié [! Qui n'était pas censé être unique] à égalité avec les attributs ID, de sorte que les scripts utilisant des identifiants ID pour accéder à des éléments DOM particuliers seraient tout simplement brisés!

Et ils ont fait comme ils écrivaient et publiaient également de nombreuses leçons de codage et des exemples [leur navigateur ne reconnaîtrait pas de toute façon], tels que document.all.ElementID.property au lieu de ElementID.property au moins pour le rendre inefficace et donner au navigateur plus de temps système au cas où il ne le ferait pas simplement au domaine HTML en utilisant le même jeton pour le nom (maintenant [1996-97], déconseillé) et l'attribut ID standard fournissant avec la même valeur symbolique.

Ils ont facilement réussi à convaincre, à l’époque, une armée écrasante d’amateurs ignorants en rédaction de code que les noms et les identifiants sont pratiquement les mêmes, sauf que l’attribut ID est plus court et donc plus respectant les octets et plus pratique pour le codeur que l’ancienne propriété Name. Ce qui était bien sûr un mensonge. Ou bien, dans leurs articles HTML remplaçants, vous aurez besoin d'articles convaincants pour que vous deviez indiquer à la fois Nom et ID à vos balises pour qu'elles soient accessibles par le moteur de script.

Les tueurs de mosaïques [nom de code "Mozilla"] étaient tellement énervés qu'ils pensaient "si nous descendons, Internet devrait en faire de même".

Les nouveaux Microsoft - en revanche - étaient si naïfs qu'ils ont pensé qu'ils devaient conserver la propriété Name obsolète et marquée pour suppression et la traiter comme s'il s'agissait d'un identifiant unique afin de ne pas compromettre la fonctionnalité de script de anciennes pages codées par les stagiaires de Netscape. Ils avaient tort mortellement ...

Et le retour d’une collection d’éléments en conflit d’identités ne constituait pas non plus une solution à ce problème délibéré créé par l’homme. En fait, cela a déjoué tout le but.

Et c’est la seule raison pour laquelle le W3C est devenu laid et nous a donné des idioties telles que document.getElementById et la fichue syntaxe rococo qui l'accompagne ... (...)

2
Bekim Bacaj