2010-08-08 13 views
276

Trabajando en una idea para un simple envoltorio HTMLElement me topé con la siguiente Internet   Explorer y Chrome:¿Los elementos del árbol DOM con identificadores se convierten en variables globales?

Para un HTMLElement dado con la identificación en el árbol DOM, es posible recuperar el div utilizando su ID como el nombre de la variable. Así que para un div como

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

en Internet Explorer 8 y Chrome que puede hacer:

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

o

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

Por lo tanto, quiere decir esto cada elemento en el árbol DOM se convierte a una variable en el espacio de nombres global? ¿Y también significa que uno puede usar esto como un reemplazo para el método getElementById en estos navegadores?

+3

Véase también [¿Por qué no nos ¿usar identificadores de elementos como identificadores en JavaScript?] (http://stackoverflow.com/q/25325221/1048572) sobre por qué no se debe usar, y [¿Existe alguna especificación de que el ID de los elementos se convierta en variable global?] (http://stackoverflow.com/q/6381425/1048572) sobre cómo se especifica. – Bergi

+0

@Bergi, el comentario que dice no hacer esto ahora está desactualizado e incluso inválido. Por lo tanto, no puedo encontrar una razón concreta para no usar esta característica. –

+0

@EdmundReed Es posible que desee volver a leer la respuesta de la pregunta vinculada: sigue siendo una mala idea: "* las variables globales implícitamente declaradas *" tienen compatibilidad incorrecta con herramientas y "* conducen a código quebradizo *". No lo llame "característica", la respuesta a continuación explica cómo es solo un error que se convirtió en parte del estándar por razones de compatibilidad. – Bergi

Respuesta

323

Lo que se supone que ocurre es que los 'elementos nombrados' se agregan como propiedades aparentes del objeto document. 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 objeto window. Esto es doblemente malo porque ahora debe evitar nombrar sus elementos después de cualquier miembro del objeto document o window que usted (o cualquier otro código de biblioteca en su proyecto) quiera usar.

También significa que estos elementos son visibles como variables globales. Afortunadamente, en este caso, las declaraciones globales var o function en su código las sombrean, por lo que no necesita preocuparse tanto por nombrarlas aquí, pero si intenta hacer una asignación a una variable global con un nombre discordante, lo olvidará. para declararlo var, obtendrá un error en IE, ya que trata de asignar el valor al elemento en sí.

En general, se considera una mala práctica omitir var, así como confiar en que los elementos con nombre sean visibles en window o como globales. Se adhiere al document.getElementById, que es más ampliamente compatible y menos ambiguo. Puede escribir una función de envoltura trivial con un nombre más corto si no le gusta el tipeo. De cualquier manera, no tiene sentido usar un caché de búsqueda de identificador a elemento, porque los navegadores normalmente optimizan la llamada getElementById para usar una búsqueda rápida de todos modos; Todo lo que obtienes es problemas cuando los elementos cambian id o se agregan/quitan del documento.

Opera copiado IE, entonces WebKit se unieron, y ahora tanto la práctica previamente no estandarizado de poner elementos nombrados en document propiedades, y el ya-IE-única práctica de ponerlos en window son beingstandardised por HTML5, cuyo enfoque es documentar y estandarizar cada práctica terrible que nos infligen los autores de los navegadores, convirtiéndola en parte de la web para siempre. Entonces Firefox 4 también lo apoyará.

¿Qué son los "elementos nombrados"? Cualquier cosa con un id, y cualquier cosa con un name se utiliza para fines de 'identificación': es decir, formularios, imágenes, anclas y algunos otros, pero no otras instancias no relacionadas de un atributo name, como nombres de control en campos de entrada de formulario, nombres de parámetros en <param> o tipo de metadatos en <meta>. 'Identificación' name s son los que deberían evitarse a favor de id.

+4

Esa es una respuesta clara, gracias. No fue mi idea omitir document.getElementById (bueno, de hecho, utilizo xpath cuando es posible para buscar propiedades de elementos/elementos hoy en día). Me encontré con esta (mala) práctica para los artículos con nombre y tenía curiosidad de dónde venía. Usted respondió eso lo suficiente; ahora sabemos por qué también se puede encontrar en Chrome (webkit). – KooiInc

+13

Se debe evitar una excepción a "uso de' name' "con' ', donde el atributo' name' juega un papel crítico en la formación de la clave de pares clave-valor para envíos de formularios. – Yahel

+7

FYI Firefox solo hace esto cuando se pone en modo peculiar. –

15

usted debe pegarse a getElementById() en estos casos, por ejemplo:

document.getElementById('example').innerHTML 

IE le gusta mezclar elementos con name y ID atributos en el espacio de nombres global, así que es mejor ser explícito acerca de lo que está tratando de conseguir.

36

Como se mencionó en la respuesta anterior, este comportamiento se conoce como named access on the window object. El valor del atributo name para algunos elementos y el valor del atributo id para todos los elementos están disponibles como propiedades del objeto global window. Estos se conocen como elementos con nombre. Como el window es el objeto global en el navegador, cada elemento nombrado será accesible como una variable global.

Esto fue originalmente agregado 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 (motor de renderizado de Firefox) optó por implementar esto solo en quirks mode, mientras que otros motores de renderización lo dejaron en modo estándar.

Sin embargo, a partir de Firefox 14, Firefox now supports named access en el objeto window en el modo de estándares también. ¿Por qué cambiaron esto? Resulta que todavía hay muchos sitios que dependen de esta funcionalidad en modo estándar. Microsoft incluso released a marketing demo que lo hizo, evitando que la demostración funcione en Firefox.

Webkit ha recientemente considered the opposite, relegando el acceso con nombre en el objeto window al modo peculiar solo. Decidieron no hacerlo por el mismo razonamiento que Gecko.

Tan ... loco como parece, este comportamiento ahora es técnicamente seguro de usar en la última versión de todos los principales navegadores en el modo de estándares. Pero aunque el acceso con nombre puede parecer algo conveniente, no debe usarse.

¿Por qué? Muchos de los razonamientos se pueden resumir en este artículo sobre por qué global variables are bad. En pocas palabras, tener un montón de variables globales adicionales conduce a más errores. Digamos que accidentalmente ingresas el nombre de var y escribes un id de un nodo DOM, ¡SORPRESA!

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

  • IE incorrectamente hace que el valor del atributo name sea accesible para los elementos del formulario (entrada, seleccionar, etc.).
  • Gecko y Webkit incorrectamente NO hacen accesibles las etiquetas <a> a través de su atributo name.
  • Gecko maneja incorrectamente múltiples elementos con el mismo nombre (devuelve una referencia a un solo 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, use document.getElementById para obtener una referencia a un nodo DOM por su id. Si necesita obtener una referencia a un nodo mediante su atributo name, use document.querySelectorAll.

Por favor, no propague este problema mediante el acceso con nombre en su sitio. Muchos desarrolladores web han perdido el tiempo tratando de rastrear 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, romperá algunos sitios haciendo cosas malas, pero a la larga ayudará a avanzar en la web.

Si te interesa hablo de esto con más detalle en mi blog - http://tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/.

+3

Sólo una nota a la advertencia obvia a la premisa de que "no debe ser usado". Tha Esto es, "no debe usarse A MENOS QUE resulte ser un vaquero codificado". Los cowboys de código solo lo aceptan. –

+3

@jeremyfoster a menos que "código vaquero" se refiera a alguien que usa y propaga malas implementaciones nocivas para el desarrollador, estoy totalmente en desacuerdo. –

+2

Una marca de un buen vaquero es que muchos están en desacuerdo. Pero ahora soy como el vaquero filosófico o algo así. –

3

Sí, lo hacen.

Probado en Chrome 55, Firefox 50, IE 11, es decir Edge 14, 10 y Safari
con el siguiente ejemplo:

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