¿Los elementos del árbol DOM con ID se convierten en propiedades globales?
Trabajando en una idea para un contenedor simple, HTMLElement
me topé con lo siguiente para Internet Explorer y Chrome :
Para un objeto dado HTMLElement
con un id
en 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 getElementById
método en estos navegadores?
Lo que se supone que sucede es que los "elementos con nombre" se agregan como propiedades aparentes del document
objeto. 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 window
objeto. Esto es doblemente malo porque ahora debe evitar nombrar sus elementos con el nombre de cualquier miembro del objeto document
o del window
objeto 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 var
o real function
en 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 window
o 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 getElementById
llamada para usar una búsqueda rápida de todos modos; todo lo que obtiene son problemas cuando los elementos cambian id
o 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 name
se utilice con fines de "identificación": es decir, formularios, imágenes, anclajes y algunos otros, pero no otras instancias no relacionadas de un name
atributo, como nombres de control en campos de entrada de formulario, nombres de parámetros en <param>
o escriba metadatos en <meta>
. Los 'identificantes' name
son los que deben evitarse en favor de id
.
Como se mencionó en la respuesta anterior, este comportamiento se conoce como acceso con nombre al objeto de ventana . El valor del name
atributo para algunos elementos y el valor del id
atributo para todos los elementos están disponibles como propiedades del window
objeto global. Estos se conocen como elementos con nombre. Dado que window
es 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 window
objeto ú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 var
y por casualidad escribes el id
de 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
name
atributo 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 suname
atributo. - 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.getElementById
para obtener una referencia a un nodo DOM por su id
. Si necesita obtener una referencia a un nodo por su name
atributo, 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/ .
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.