falsy - javascript void 0 como solucionar
¿Por qué document.all falsy? (4)
document.all
es un objeto no primitivo en el DOM que es falso.
Por ejemplo, este código no hace nada:
if (document.all) {
alert("hello");
}
¿Alguien puede explicar por qué es esto?
En resumen, es para que AMBAS de estas muestras de código funcionen. Los navegadores deben hacer esto para que las páginas web antiguas continúen funcionando.
Muestra 1
// Internet Explorer
if (document.all) {
useActiveX()
}
// Netscape Navigator
else {
useOldButStillWorkingCode()
}
Muestra 2
document.all.output.innerHTML = ''Hello, world!''
Los navegadores modernos ya no implementan esta cosa desactualizada. Fue presentado por IE, pero la mayoría de los otros lo "calza" para que sea compatible.
Para hacer posible la detección de navegadores (en los viejos tiempos se podía diferenciar a IE de NN probando document.all
) mientras se soportaba la sintaxis de document.all, otros navegadores realizaban la implementación "extraña" que typeof document.all
devuelve indefinido.
Opera> document.all
// prints the array-like object
Opera> typeof document.all
"undefined"
Opera> Boolean(document.all)
false
Antes de que FF dejara de apoyarlo, también mostró un comportamiento extraño como se indica en este mensaje . Puede encontrar más elementos internos en el error # 412247 de Mozilla .
También hay un hilo muy largo en el archivo de la lista de correo del W3C, que comienza con http://lists.w3.org/Archives/Public/public-html/2009Jun/0546.html
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 Todos los objetos en JavaScript son verdad según la especificación, pero en el DOM no es un objeto no primitivo. ¿Cual?
Y un violín que muestra todo el objeto falsy del documento http://jsfiddle.net/UTNkW/
Descargo de responsabilidad: Soy el tipo que tuiteó la pregunta que condujo a este hilo :) Era una pregunta que haría y respondería en mi charla de Front-Trends . Escribí ese tuit 5 minutos antes de subir al escenario.
La pregunta que estaba haciendo es la siguiente.
La especificación de ECMAScript define ToBoolean()
siguiente manera :
Como puede ver, todos los objetos no primitivos (es decir, todos los objetos que no son booleanos, un número, una cadena, undefined
o null
) son verdaderos 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
. La especificación de HTML dice:
El atributo
all
debe devolver unaHTMLAllCollection
enraizada en el nodoDocument
, cuyo filtro coincide con 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
en el valorfalse
.El agente de usuario debe actuar como si, a los efectos de los operadores
==
y!=
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 devuelva la cadena''undefined''
cuando se aplica al objeto devuelto paraall
.Estos requisitos son una violación voluntaria 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()
convierta todos los objetos al valortrue
, y no tiene disposiciones para objetos que actúan como si no estuvieranundefined
para los propósitos de ciertos operadores. Esta infracción está motivada por el deseo de compatibilidad con dos clases de contenido heredado: uno que utiliza la presencia dedocument.all
como una forma de detectar agentes de usuario heredados, y uno que solo admite esos agentes de usuario heredados y utiliza el objetodocument.all
sin probar primero su presencia.
Entonces, 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 fragmento de código de ejemplo que es muy común en páginas web antiguas, y eso lo 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, para un document.all
mucho tiempo. document.all
se usó de esta manera para detectar navegadores antiguos. Sin embargo, dado que document.all
se prueba primero, los navegadores más modernos que ofrecen ambas propiedades seguirán apareciendo en la ruta del document.all
. En los navegadores modernos, preferiríamos usar document.getElementById
, por supuesto, pero como la mayoría de los navegadores aún tienen document.all
(por otras razones de compatibilidad con versiones anteriores), nunca se accederá a los else
si document.all
fuera cierto. Si el código se hubiera 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, muchos códigos existentes lo hacen al revés.
La solución más simple para este problema es simplemente hacer que document.all
sea falso en los navegadores que aún lo imitan.