2010-10-20 19 views
13

Tuve una entrevista interesante hoy que me dejó perplejo. Me preguntaron acerca de los valores de Falsey. Tan indefinido, NaN, nulo, 0 y una cadena vacía, todos son falsos. ¿Cuál es la razón por la cual es útil saber esto en JavaScript? La única cosa que puedo pensar es en lugar de tener que hacer esto:Valores de Falsey en JavaScript

if (mystring === '' || mystring === undefined) { } 

que pueda hacer esto:

if (!mystring) 

Es esta la única aplicación útil?

+8

NaN en lugar de NAn, nulo en lugar de nulo (JavaScript distingue entre mayúsculas y minúsculas) –

+0

Una de las cosas que te encanta de la programación es tener que estar al día con los términos del idioma (inglés).¿Es "falsey" realmente un término de programación legítimo, o simplemente significa "valores falsos"? Si se trata de un término -real, y no solo geek speak, ¿dónde está una url que lo define, ya que no puedo encontrar una definición legítima del término. – Bill

+0

@Bill Creo que "truthy" y "falsy" son neologismos entonces ... http://javascript.crockford.com/style2.html –

Respuesta

15

Una de las cuestiones peligrosas de los valores de falsey que debes conocer es comprobar la presencia de una propiedad determinada.

Supongamos que desea probar la disponibilidad de una nueva propiedad; Cuando esta propiedad puede realmente tener un valor de 0 o "", no se puede simplemente comprobar su disponibilidad utilizando

if (!someObject.someProperty) 
    /* incorrectly assume that someProperty is unavailable */ 

En este caso, es imprescindible de verificación para que sea realmente presente o no:

if (typeof someObject.someProperty == "undefined") 
    /* now it's really not available */ 

también tenga en cuenta que NaN no es igual a nada, ni siquiera a sí mismo (NaN != NaN).

+1

Pero puede legítimamente establecer una propiedad como indefinida, rompiendo así esta prueba. Es casi seguro que es mejor utilizar algún objeto Objeto.apropiedad, y comprobarlo recursivamente si realmente le importa si la propiedad existe en algún lugar de la cadena de prototipos de los objetos. – Angiosperm

+0

@Angiosperm En JavaScript, los objetos son dinámicos de todos modos, por lo que no hay diferencia práctica entre un objeto que no tiene una propiedad y un objeto con una propiedad establecida en 'undefined' –

+0

@ Šime Vidas Situación: nuestra aplicación llama a una ubicación remota para verificar la existencia de un recurso La existencia del recurso es constante durante el ciclo de vida de la aplicación. Esta verificación puede ser costosa, por lo que queremos comenzar a almacenar en caché el resultado de la llamada. Hagamos eso estableciendo alguna propiedad de un objeto para el resultado de esa llamada. El código existente simplemente verifica si el resultado de la llamada es 'indefinido' para decidir si el recurso existe.Para no tener que cambiar nuestra interfaz actual, el mecanismo de caché debería verificar si realmente existe la propiedad adecuada, en lugar de simplemente no está definida. – Angiosperm

3

Es útil para detectar si un navegador es tiene objetos predefinidos específicos:

if(!!navigator.geolocation){ 
    // executes if the browser has geolocation support 
} 

if(!!document.createElement('canvas').getContext){ 
    // executes if the browser supports <canvas> 
} 

Explicación: navigator.geolocation es un objeto o indefinido. En el caso de que sea un objeto, !navigator.geolocation devolverá falso; si no está definido, devolverá verdadero. Por lo tanto, para verificar si un navegador tiene geolocalización habilitada, quiere 'voltear' el booleano una vez más, agregando otro !.

+0

Entonces, si hiciera if (! Navigator.geolocation) {} y no está definido, ¿esto daría como resultado false? –

+1

No lo entiendo ... ¿Cuál es la diferencia entre 'if (!! foo.bar)' y 'if (foo.bar)'? –

+0

@elduderino No, volvería a ser cierto. Los ! el operador primero convierte su operando en un valor booleano y luego lo cambia ... En el caso de que el navegador.geolocation no esté definido, se convertirá en el valor booleano falso, y luego se cambiará a verdadero ... –

3

Es importante saber que 0 evalúa a false para evitar hacer cosas como:

if(str.indexOf('foo')) 
+0

ah sí, muy bien. –

+0

¿Cómo funcionaría eso? Devuelve -1 cuando no se encuentra nada, que no es un valor falso. –

+0

@Nick: El punto es que no funcionaría. –

3

También son útiles para establecer los valores por defecto ...

function foo(bar){ 
    alert(bar || "default"); 
} 

Sé que muchos de personas intentan hacer

if (typeof(foo) === "undefined"){} 

para moverse por la falsedad, pero eso tiene ts propios problemas porque

typeof(null) === "object" 

por alguna razón

+0

Sí, lo sabía sobre null. Extraño. Buenos ejemplos. Gracias –

+0

@elduderine una cosa más desagradable sobre null es isNaN (null) === false. – Angiosperm

+0

Tu ejemplo (bar || "default") es probablemente un antipattern. Esto se debe a que se activará en la cadena vacía que el usuario de su función puede haber pretendido que sea el valor de la barra (he encontrado este error varias veces en las bibliotecas). Incluso si el contexto significa que usted entendió esto, no será claro para el usuario de su función que este es el caso sin un comentario. Es mejor evitar este estilo por completo para los valores que pueden ser cadenas (""), números (NaN) o booleanos (falso). – kybernetikos

5

Es importante entender cómo funciona esto en JS, lo que no está sorprendido. No necesariamente lo que es falsey, sino lo que es verdad y cómo se comparan entre sí.

Un ejemplo es que '0' se considera igual a 0 con ==, pero no es igual a '' - aunque 0 es. La comparación de JavaScript no siempre es transitiva.

Esto significa que solo porque (foo==bar && bar==fizz) es cierto, (foo==fizz) no siempre es cierto. Para ir con el ejemplo anterior, '0' == 0 y 0 == '', pero '0'! = '' - porque está comparando cadenas en la última instancia, por lo que se los compara como cadenas y no se los coacciona a los números.

7

Hay dos problemas con los valores de 'falsey' en JavaScript.

Primero está el esquema de conversión oficial, que es el que devuelve Boolean (x). Esto devuelve falso cuando x es falso o 0 o NaN o nulo o indefinido o "" y verdadero de lo contrario. Este es el mismo comportamiento que el

if (condition) {/*true path*/} else {/*false path*/} 

es decir, se ejecuta el camino falso si booleana (condición) habría vuelto falso y el verdadero camino está ejecutado de otra manera. Este comportamiento se usa a menudo para verificar si una propiedad está definida. Sin embargo, hacer eso no es seguro a menos que esté seguro de que la propiedad sería un objeto o una matriz si está definida. La forma más segura de probar si una propiedad se define es hacer

if (property != null) { /*property is defined*/} 

el que se asegura de que la propiedad no es nulo o no definido. Si sólo quiere asegurarse de que la propiedad no está definido qué

if (property !== undefined) { /*property is not undefined (but may be null)*/ } 

(observe el extra en =! ==).

En segundo lugar, hay todos los valores que == falso. Esto es todo lo que se puede forzar a 0 (que es lo que se coacciona a falso). Esto incluye todos los valores que se convierten en falsos excepto NaN (que no puede == falso en virtud de que nunca == nada), nulo e indefinido. Pero también incluye todos los objetos que cuando se convierten en una cadena y luego se convierten en un número son iguales a 0. Por ejemplo, esto incluye todo lo que cuando se convierte a una cadena es la cadena vacía "" o "0" o "-0 "o "0" o "0x00" o "000" o "0E0" o "0,0000" ...., por ejemplo,

({toString: function() {return "-00.0e000";}}) == false 

es cierto. Curiosamente, esto incluye la matriz vacía y cualquier agrupación de matrices que contenga un solo elemento que devuelva una cadena vacía o 0, ya que las matrices procesadas como cadenas muestran solo los contenidos sin los corchetes circundantes. Es decir,

[[[[0]]]] == false; // Because [[[[0]]]].toString() === "0" 
[] == false; 
[[[""]]] == false; 
["0"] == false; 
[[({toString: function() {return "0";}})]] == false; 

El algoritmo completo para calcular == false se describe here.

La razón por la que esto importa es porque puede llevar a errores sutiles y difíciles de encontrar si no entiende la mayoría de estas reglas. Las conclusiones más importantes son, probablemente, cómo funciona el if (condition) y que el uso de === evita la mayoría de las otras cosas locas.

Cuestiones relacionadas