¿Tiene JavaScript evaluación de "cortocircuito"?


101

Me gustaría saber si JavaScript tiene una evaluación de "cortocircuito" como && Operator en C #. Si no es así, me gustaría saber si existe una solución alternativa que tenga sentido adoptar.


2
De nada. Lo agregué https://www.google.com/search?q=site:stackoverflow.com+%scomo un atajo de búsqueda (Chrome / Firefox) para acelerar las búsquedas.
Rob W

También aquí una respuesta a mi pregunta developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
GibboK

Respuestas:


118

Sí, JavaScript tiene evaluación de "cortocircuito".

if (true == true || foo.foo){
    // Passes, no errors because foo isn't defined.
}

Demo en vivo

if (false && foo.foo){
    // Passes, no errors because foo isn't defined.
}

Demo en vivo


8
Entonces, ¿el cortocircuito es el estándar en JS?
GibboK

1
Gracias gdoron, por favor ayúdame a entender ... en C # también tengo un operador binario como y, por lo tanto, ambos operandos deben ser verdaderos para pasar, en cambio con && en C
GibboK

1
@GibboK. Entonces, obviamente, no puede haber un Short-circuitcon ese operador lógico. Pruébelo usted mismo. Usa mi demo.
gdoron apoya a Monica

2
@GibboK: Consulte esta referencia de operador . Y sí, también hay un operador AND binario en JS.
Bergi

5
@GibboK. ¡SÍ en el estándar! Pero un buen comentario, como en tiempos de la magia de compilación JIT en implementaciones de javascript, uno realmente quiere saber si algo es "el estándar", o potencialmente sujeto a la implementación. La forma en que se evalúa una declaración condiciones, con binarios operadores lógicos y (corto curcuit) es un comportamiento estándar ecma-international.org/ecma-262/5.1/#sec-11.11
humanityANDpeace

23

Esta respuesta entra en gran detalle sobre cómo funciona en JavaScript, con todos los problemas y también temas relevantes como la precedencia del operador, si está buscando una definición rápida y ya comprende cómo funciona el cortocircuito, recomendaría verificar otras respuestas.


Lo que (pensamos) sabíamos hasta ahora:

Primero, inspeccionemos el comportamiento con el que todos estamos familiarizados, dentro del if()bloque, donde usamos &&para verificar si las dos cosas son true:

if (true && true) {
   console.log('bar');
} 

Ahora, su primer instinto probablemente sea decir: 'Ah sí, bastante simple, el código ejecuta la declaración si ambos expr1y expr2se evalúan como true'

Bueno, sí y no. Es técnicamente correcto, ese es el comportamiento que describió, pero no es exactamente así como se evalúa el código y tendremos que profundizar más para comprenderlo completamente.


¿Cómo se interpreta exactamente &&y ||?:

Es hora de mirar "bajo el capó del motor ". Consideremos este ejemplo práctico:

function sanitise(x) {
  if (isNaN(x)) {
    return NaN;
  }
  return x;
}

let userinput = 0xFF; // as an example
const res = sanitise(userinput) && userinput + 5

console.log(res);

Bueno, el resultado es 260... pero ¿por qué? Para obtener la respuesta, debemos comprender cómo funciona la evaluación de cortocircuito.

Por la definición de MDN, el &&operador en expr1 && expr2se ejecuta de la siguiente manera:

Si expr1se puede convertir a true, devuelve expr2; si no, vuelve expr1.

Esto significa que, en nuestro ejemplo práctico, const resse evalúa de la siguiente manera:

  1. Invocando expr1-sanitise(0xFF)
  2. 0xFF es un número hexadecimal válido para 250, de lo contrario devolvería NaN
  3. El expr1devolvió un valor "verdadero", tiempo para ejecutar expr2 (de lo contrario, me detendría como NaNes falso)
  4. Dado que userinputes Truthy (un número), puedo añadir +5a ella
  • "Verdad" significa que la expresión se puede evaluar como verdadera. Aquí hay una lista de expresiones veraces y falsas .

Así que aquí pudimos evitar ifbloqueos adicionales y isNaNverificaciones adicionales con un simple uso del &&operador.


Cómo funciona realmente:

A estas alturas, al menos deberíamos tener una idea de cómo los operadores trabajan. La regla universal es:

  • (some falsy expression) && expr evaluará a una expresión falsa
  • (some truthy expression) || expr evaluará a la expresión veraz

Aquí hay algunos ejemplos adicionales para una mejor comprensión:

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() && b() ){
     console.log('foobar'); 
}

//Evaluates a() as false, stops execution.

function a() { console.log('a'); return false; }
function b() { console.log('b'); return true; }

if ( a() || b() ){
     console.log('foobar'); 
}

/* 1. Evaluates a() as false
   2. So it should execute expr2, which is `b()`
   3. b() returned as true, executing statement `console.log('foobar');`
*/


Una última cosa molesta, pero muy importante [precedencia del operador]:

Bien, ¡espero que lo estés entendiendo! Lo último que necesitamos saber es una regla sobre la precedencia de los operadores, es decir:

  • El &&operador siempre se ejecuta antes que el ||operador.

Considere el siguiente ejemplo:

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log(a() || b() && c());

// returns a() and stops execution

Esto volverá como, quizás confuso para algunos como a(). La razón es bastante simple, es solo nuestra vista lo que nos engaña, porque estamos acostumbrados a leer de izquierda a derecha. Saquemos el console.log()y lo que no y centrémonos únicamente en la evaluación

true || false && false

Ahora, para entender esto:

  1. Dijimos que el &&operador tiene precedencia, por lo que se evalúa como el primero. Para ayudarnos a imaginar mejor la evaluación, piense en la definición

    expr1 && expr2

    Dónde:

    • expr2 es false
    • expr1 es true || false
  2. Así que esa fue la parte complicada, ahora true || falsese evalúa (el expr1lado izquierdo del &&).

    • Dado el ||operador detiene la ejecución si expr1 || expr2en expr1evalúa como Truthy, el expr1se ejecuta y se detiene la ejecución de código.
  3. El valor devuelto es true

Bueno ... eso fue bastante complicado, todo debido a unas pocas reglas y semánticas extrañas. Pero recuerde, siempre puede escapar de la precedencia del operador con (), al igual que en matemáticas

function a() { console.log('a'); return true;}
function b() { console.log('b'); return false;}
function c() { console.log('c'); return false;}

console.log((a() || b()) && c());

/* 1. The () escape && operator precedence
   2. a() is evaluated as false, so expr2 (c()) to be executed
   3. c()  
*/


Yo 1) no usaría la palabra "compilador". "motor" es más preciso. 2) No hablar expr1y expr2 o condition1o lo que sea, eso es sólo confuso. Decida por uno, también podría introducir variables locales, por ejemplo. const expr1 = true; if(expr1 && ...)
Jonas Wilms

@JonasWilms gracias por la entrada, modificó la respuesta en consecuencia.
Samuel Hulla

1
Esto todavía no responde directamente a la pregunta formulada.
Kevin B

7
Esta es la mejor "gran respuesta que no responde explícitamente a la pregunta" que he visto ...
Gerardo Furtado

1
¡Esta es la respuesta correcta con una explicación profunda, debe marcarse como aceptada y votada mucho más de lo que es actualmente!
Alexander Kim
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.