2010-06-03 11 views
13

vi esta construcción con el fin de obtener el ancho del navegador ventana gráfica:¿Por qué Javascript O devuelve un valor que no sea verdadero/falso?

function() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; } 

entiendo las peculiaridades del navegador involucrados. Lo que no entiendo es por qué || devuelve el valor. Así que probé este alert(undefined || 0 || 3); y efectivamente, alerta 3. Encuentro esto extraño, porque espero true o false. ¿Alguien podría explicar lo que está pasando?

+0

¿Tiene 'alerta (undefined && 0 && 3)' 'retorno 0'? –

+2

@Rising Star: ¿por qué preguntar al OP cuando puedes hacerlo tú mismo? ... También, para mí, devuelve 'undefined'. – Matchu

+3

FYI: si quieres un valor de verdad, haz '!! (undefined || 0 || 3)' – Matt

Respuesta

13

Tome un vistazo a la sección de estándares de ECMAScript 11.11 Binary Logical Operators

la LogicalORExpression producción: LogicalORExpression || LogicalANDExpression se evalúa como a continuación:

1.Evalúe LogicalORExpression.

2. Llamada GetValue (Resultado (1)).

3. Llamar a ToBoolean (Resultado (2)).

4.Si el resultado (3) es verdadero, devuelva Resultado (2).

5.Evaluate LogicalANDExpression.

6. Llamada GetValue (Resultado (5)).

7.Return Resultado (6).

Así que evalúa la booleano conversión de cada operando, pero devuelve el valor real del operando.

Si usted quiere saber cómo Javascript convierte los valores a un valor lógico, véase la sección 9.2 ToBoolean

17

El operador JavaScript || se define para devolver el valor izquierda si se evalúa como un valor Truthy, de lo contrario el valor correcto en vez de volver true sí. Así es como se define en la especificación.

Sé que puede ser molesto a veces, puede terminar accidentalmente manteniendo una referencia a algo que no quiere retener, pero también permite el truco útil que tiene su ejemplo. Todo tiene sus pros y sus contras.

4

La función O es una evaluación O de cortocircuito - devuelve el primer elemento que no es falso, o el último elemento falso en caso contrario.

Esto es realmente muy útil, para que pueda escribir expresiones como

a = a || someValue; 

¿Qué es la misma que

if (a==null) 
    a = someValue; 
+1

No es solo "no nulo". La cadena vacía y el cero numérico se tratan como "falso". El pseudovalor "indefinido" también se trata como "falso", aunque allí es donde las cosas se vuelven un poco más complejas. – Pointy

+0

editado: ahora usa verdadero y falso como definiciones. Al mirar el estándar ECMA, convierte cada valor en booleano para la prueba, a través de toBoolean pero devuelve el valor mismo después de la prueba. – mdma

9

No pensar en él como "o". Es más como un dispositivo de control de flujo dentro de una expresión. El valor de a || expresión es el valor de la primera subexpresión que es "verdad". Por lo tanto, la evaluación de la serie de subexpresiones se detiene en algún punto, como si

expr1 || expr2 || expr3 

eran

(function() { 
    var rv = expr1; 
    if (rv) return rv; 
    rv = expr2; 
    if (rv) return rv; 
    return expr3; 
})() 
1

Algunos valores, tales como cero, "" o undefined, son tratados como falsa. Cualquier otra cosa es verdadera, por lo que el operador || simplemente devuelve el primer valor distinto de cero (es decir, verdadero) en el par que se le otorga. Esto es útil para trucos como el código anterior, pero supongo que no se agregó al lenguaje solo para permitirte omitir la declaración impar.

Sospecho que puede haberse originado como un ajuste de rendimiento, ya que los lenguajes de nivel superior (como BASIC ... sí, quizás una definición impar de nivel superior) usaron constantes fijas para verdadero y falso - a menudo 0 y -1, o 0 y 1.

+2

Mire esa definición de "cualquier cosa que no sea cero". 'false',' undefined', y '" "' no son cero, pero no se consideran verdaderas. – Matchu

+0

@Matchu gracias, ese es mi fondo Perl mostrando a través de. :(Fixed. –

+0

Me gusta pensar en el comportamiento de || y && como 'el valor del argumento que determina la veracidad o falsedad se devuelve'. –

2

Así es como está diseñado. ||, como && es un operador de cortocircuito, las expresiones se evalúan en orden, se detienen después de que una expresión cumple los criterios y arroja el resultado de la expresión.Lo mismo puede decirse de &&:

var myObj = { "Test": { "Foo":"Bar" } }; 
var myObj2 = { "Foo": "Bar" }; 

alert(myObj.Test && myObj.Test.Foo); // will alert "Bar"; 
alert(myObj2.Test && myObj2.Test.Foo); // will alert undefined; 
Cuestiones relacionadas