¿Los elementos del árbol DOM con ID se convierten en propiedades globales?

Resuelto KooiInc asked hace 14 años • 6 respuestas

Trabajando en una idea para un contenedor simple, HTMLElementme topé con lo siguiente para Internet Explorer y Chrome :

Para un objeto dado HTMLElementcon un iden el árbol DOM, es posible recuperarlo <div>usando su ID como nombre de variable o como propiedad de window. Así que por un <div>me gusta

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

en Internet Explorer 8 y Chrome puedes hacer:

alert(example.innerHTML); // Alerts "some text".

o

alert(window["example"].innerHTML); // Alerts "some text".

Entonces, ¿significa esto que cada elemento del árbol DOM se convierte en una propiedad del objeto global? ¿Y significa también que se puede usar esto como reemplazo del getElementByIdmétodo en estos navegadores?

KooiInc avatar Aug 08 '10 19:08 KooiInc
Aceptado

Lo que se supone que sucede es que los "elementos con nombre" se agregan como propiedades aparentes del documentobjeto. Esta es una muy mala idea, ya que permite que los nombres de los elementos entren en conflicto con las propiedades reales de document.

IE empeoró la situación al agregar también elementos con nombre como propiedades del windowobjeto. Esto es doblemente malo porque ahora debe evitar nombrar sus elementos con el nombre de cualquier miembro del objeto documento del windowobjeto que usted (o cualquier otro código de biblioteca en su proyecto) desee usar.

También significa que estos elementos son visibles como variables de tipo global. Afortunadamente, en este caso, cualquier declaración global varo real functionen su código las oculta, por lo que no necesita preocuparse tanto por nombrar aquí, pero si intenta realizar una asignación a una variable global con un nombre que choca y se olvida de declarar Si lo hace var, obtendrá un error en IE cuando intente asignar el valor al elemento mismo.

Generalmente se considera una mala práctica omitir var, así como confiar en que los elementos con nombre sean visibles en windowo como globales. Cíñete a document.getElementById, que tiene más apoyo y es menos ambiguo. Puede escribir una función contenedora trivial con un nombre más corto si no le gusta escribirla. De cualquier manera, no tiene sentido usar una caché de búsqueda de id a elemento, porque los navegadores normalmente optimizan la getElementByIdllamada para usar una búsqueda rápida de todos modos; todo lo que obtiene son problemas cuando los elementos cambian ido se agregan/eliminan del documento.

Opera copió IE, luego WebKit se unió y ahora HTML5 está estandarizando tanto la práctica previamente no estandarizada de colocar elementos con nombre en propiedades como la práctica que antes eradocument exclusiva de IE de colocarlos en HTML5, cuyo enfoque es documentar y estandarizar cada terrible práctica que nos infligen los autores de navegadores, haciéndolos parte de la web para siempre. Entonces Firefox 4 también admitirá esto.window

¿Qué son los 'elementos con nombre'? Cualquier cosa con un id, y cualquier cosa con un que namese utilice con fines de "identificación": es decir, formularios, imágenes, anclajes y algunos otros, pero no otras instancias no relacionadas de un nameatributo, como nombres de control en campos de entrada de formulario, nombres de parámetros en <param>o escriba metadatos en <meta>. Los 'identificantes' nameson los que deben evitarse en favor de id.

bobince avatar Aug 08 '2010 13:08 bobince

Como se mencionó en la respuesta anterior, este comportamiento se conoce como acceso con nombre al objeto de ventana . El valor del nameatributo para algunos elementos y el valor del idatributo para todos los elementos están disponibles como propiedades del windowobjeto global. Estos se conocen como elementos con nombre. Dado que windowes el objeto global en el navegador, cada elemento nombrado será accesible como una variable global.

Esto fue agregado originalmente por Internet Explorer y finalmente fue implementado por todos los demás navegadores simplemente por compatibilidad con sitios que dependen de este comportamiento. Curiosamente, Gecko (el motor de renderizado de Firefox) optó por implementar esto sólo en modo peculiar , mientras que otros motores de renderizado lo dejaron activado en modo estándar.

Sin embargo, a partir de Firefox 14, Firefox ahora también admite el acceso con nombre al objeto en modo estándar. window¿Por qué cambiaron esto? Resulta que todavía hay muchos sitios que dependen de esta funcionalidad en modo estándar. Microsoft incluso lanzó una demostración de marketing que así lo hizo, impidiendo que la demostración funcionara en Firefox.

Webkit ha considerado recientemente lo contrario , relegando el acceso con nombre al windowobjeto únicamente al modo peculiar. Decidieron no hacerlo por el mismo razonamiento que Gecko.

Entonces… por loco que parezca, este comportamiento ahora es técnicamente seguro de usar en la última versión de todos los principales navegadores en modo estándar . Pero aunque el acceso con nombre puede parecer algo conveniente, no debería usarse .

¿Por qué? Gran parte del razonamiento se puede resumir en este artículo sobre por qué las variables globales son malas . En pocas palabras, tener un montón de variables globales adicionales genera más errores. Digamos que accidentalmente escribes el nombre de un nodo DOM vary por casualidad escribes el idde un nodo DOM, ¡SORPRESA!

Además, a pesar de estar estandarizado, todavía existen bastantes discrepancias en las implementaciones de acceso con nombre del navegador.

  • IE hace que el valor del nameatributo sea accesible incorrectamente para los elementos del formulario (entrada, selección, etc.).
  • Gecko y Webkit incorrectamente NO hacen que <a>las etiquetas sean accesibles a través de su nameatributo.
  • Gecko maneja incorrectamente varios elementos con el mismo nombre (devuelve una referencia a un único nodo en lugar de una matriz de referencias).

Y estoy seguro de que hay más si intenta utilizar el acceso con nombre en casos extremos.

Como se menciona en otras respuestas, utilice document.getElementByIdpara obtener una referencia a un nodo DOM por su id. Si necesita obtener una referencia a un nodo por su nameatributo, utilice document.querySelectorAll.

Por favor, no propague este problema utilizando acceso con nombre en su sitio. Muchos desarrolladores web han perdido el tiempo intentando localizar este comportamiento mágico . Realmente necesitamos tomar medidas y hacer que los motores de renderizado desactiven el acceso con nombre en el modo estándar. En el corto plazo, arruinará algunos sitios que hacen cosas malas, pero en el largo plazo ayudará a que la web avance.

Si está interesado, hablo de esto con más detalle en mi blog: https://www.tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/ .

TJ VanToll avatar Jul 27 '2012 15:07 TJ VanToll

Debes ceñirte a getElementById()estos casos, por ejemplo:

document.getElementById('example').innerHTML

A IE le gusta mezclar elementos name y ID atributos en el espacio de nombres global, por lo que es mejor ser explícito sobre lo que estás intentando obtener.

Nick Craver avatar Aug 08 '2010 12:08 Nick Craver