document.all
es un objeto no primitivo en el DOM que es falso.¿Por qué document.all falsy?
Por ejemplo, este código no hace nada:
if (document.all) {
alert("hello");
}
Puede alguien explicar por qué esto es?
document.all
es un objeto no primitivo en el DOM que es falso.¿Por qué document.all falsy?
Por ejemplo, este código no hace nada:
if (document.all) {
alert("hello");
}
Puede alguien explicar por qué esto es?
document.all no es el único objeto que es falso. Se publicó otra pregunta sobre esto y, como el ejemplo del violín en la respuesta muestra que hay muchos objetos falsy en el documento. El monto varía según el navegador utilizado.
Ver esta pregunta All objects in JavaScript are truthy per the spec, but in the DOM one non-primitive object is not. Which?
Y un violín que deben mostrarse todos los objetos del documento Falsy http://jsfiddle.net/UTNkW/
La prueba a la que se vinculó es incorrecta de varias maneras. Solo buscamos objetos no primitivos que son falsos. Su prueba devuelve una gran cantidad de valores 'null'. Consulte http://stackoverflow.com/questions/10348995/all-objects-in-javascript-are-truthy-per-the-spec-but-in-the-dom-one-non-primit/10349366#comment13404885_10351511. –
navegadores modernos no implementan esta cosa obsoleta más. Fue presentado por IE, pero la mayoría de los otros lo "calza" para que sea compatible.
Para hacer posible la detección del navegador (en los viejos días se notaba IE aparte de NN mediante pruebas de document.all
) mientras que el apoyo document.all sintaxis, otros navegadores hizo la ejecución "raro" que typeof document.all
vuelve indefinida.
Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false
Antes FF abandonado el soporte para ello, sino que también mostraron un comportamiento extraño como se indica en this message. Puede encontrar más información interna en Mozilla bug #412247.
También hay un very long thread en el archivo de lista de correo del W3C, comenzando con http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html
responsabilidad:I’m the guy who tweeted the question that led to this thread :) Fue una pregunta que me gustaría hacer y contestar en mi Front-Trends charla. Escribí ese tuit 5 minutos antes de subir al escenario.
La pregunta que estaba haciendo es la siguiente.
La especificación ECMAScript defines ToBoolean()
as follows:
Como se puede ver, todos los objetos no primitivos (es decir, todos los objetos que no son un booleano, un número, una cadena, undefined
o null
) son verdad según la especificación. Sin embargo, en el DOM, hay una excepción a esto: un objeto DOM que es falso. ¿Sabes cuál es?
La respuesta es document.all
. The HTML spec dice:
El atributo
all
debe devolver unHTMLAllCollection
enraizado en el nodoDocument
, cuyo filtro equivale a todos los elementos.El objeto devuelto para todos tiene varios comportamientos inusuales:
El agente de usuario debe actuar como si el operador
ToBoolean()
en JavaScript convierte el objeto devuelto paraall
al valorfalse
.El agente de usuario debe actuar como si, a los efectos de los
==
y!=
operadores en JavaScript, el objeto devuelto paraall
es igual al valorundefined
.El agente de usuario debe actuar de tal manera que el operador
typeof
en JavaScript devuelve la cadena'undefined'
cuando se aplica al objeto devuelto porall
.Estos requisitos son una violación deliberada de la especificación de JavaScript vigente en el momento de la escritura (ECMAScript edición 5). La especificación JavaScript requiere que el operador
ToBoolean()
convertir todos los objetos de valor a latrue
, y no tiene disposiciones para los objetos que actúan como si fueranundefined
a los efectos de ciertos operadores. Esta violación está motivado por un deseo de compatibilidad con dos clases de contenido heredado: uno que utiliza la presencia dedocument.all
como una forma de detectar los agentes de usuario Legacy, y uno que sólo admite los agentes de usuario legado y utiliza el objetodocument.all
sin probar primero su presencia.
Por lo tanto, document.all
es la única excepción oficial a esta regla de ECMAScript. (En Opera, document.attachEvent
etc. también son falsas, pero eso no se especifica en ninguna parte).
El texto anterior explica por qué se hizo esto. Pero aquí hay un ejemplo fragmento de código que es muy común en las páginas web de edad, y que ilustrará más a fondo:
if (document.all) {
// code that uses `document.all`, for ancient browsers
} else if (document.getElementById) {
// code that uses `document.getElementById`, for “modern” browsers
}
Básicamente, durante mucho tiempo document.all
se utiliza de este modo para detectar navegadores antiguos. Sin embargo, dado que el document.all
se prueba por primera vez, los navegadores más modernos que ofrecen ambas propiedades seguirán en la ruta del código document.all
. En los navegadores modernos, preferiríamos usar document.getElementById
, por supuesto, pero como la mayoría de los navegadores todavía tienen document.all
(por otras razones de compatibilidad con versiones anteriores) el else
nunca sería accedido si document.all
fuera cierto. El código había sido escrito de manera diferente, esto no sería un problema:
if (document.getElementById) {
// code that uses `document.getElementById`, for “modern” browsers
} else if (document.all) {
// code that uses `document.all`, for ancient browsers
}
Pero, lamentablemente, una gran cantidad de código existente lo hace al revés.
La solución más simple para este problema es hacer que document.all
sea falso en navegadores que aún lo imitan.
Respuesta bastante complicada para una característica obsoleta. – adrianp
@adrian Bienvenido a la Web, donde todo es complicado debido a las características heredadas :) –
Ok, llámame un flojo @@@, vuélveme a votar y piensa que soy un hereje, pero desde que jQuery dejó $ .browser reinicié su uso para una detección de navegador rápida y sucia.
Déjenme explicar por qué y cuándo: No quiero verificar si una (sub) versión específica de IE admite algo, ni tampoco quiero agregar complementos o funciones personalizadas que no siempre funcionen o que necesiten actualizarse o incluso reemplazado cada vez que Microsoft lanza una actualización, solo quiero saber si necesito agregar un setTimeout a mi función init para evitar que IE se cuelgue o congele, y no quiero paralizar navegadores más confiables en el proceso.
Sea honesto, todos sabemos que Microsoft NUNCA lo descartará (por compatibilidad con versiones anteriores de las webapps de las grandes empresas basadas en IE, que el Señor las perdone) y los otros proveedores de navegadores seguirán, como siempre ha sido desde la muerte (no tan inmerecida) de Netscape.
Y en mi humilde opinión, eso es también un comportamiento compatibles con HTML5;)
Microsoft lo ha "descartado", han hecho document.all falsy en IE 11. http://www.nczonline.net/ blog/2013/07/02/internet-explorer-11-dont-call-me-ie/ –
¡Oh, idiota! Necesito cambiarlo de document.all to document.all [0], creo que estoy agregando modernizr lib en todas partes y rediseñando todo. :) – Dariozzo
por cierto: no es cortés burlarse del mal inglés de alguien cuando en realidad puedes hablar solo el tuyo. – Dariozzo
En resumen, es para hacer Ambas código de muestras de trabajo. Los navegadores deben hacer esto para que las páginas web antiguas continúen funcionando.
// Internet Explorer
if (document.all) {
useActiveX()
}
// Netscape Navigator
else {
useOldButStillWorkingCode()
}
document.all.output.innerHTML = 'Hello, world!'
navegadores modernos no implementan esta cosa obsoleta más. Es un "estándar" de IE, Opera también lo "calza". – Bergi
@Nanne la pregunta es: ¿alguien puede explicar por qué el código no hace nada? Si no se implementa, será falso y no pasará nada. Entonces pienso, es una respuesta. –
¿Pero la pregunta también indicó que estamos tratando con un objeto no nulo? Tal vez lo leí mal, pero asumí que eso significa que en la prueba estaba allí, ¿pero no se activó? – Nanne