JavaScript 有“短路”评估吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12554578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:41:30  来源:igfitidea点击:

Does JavaScript have "Short-circuit" evaluation?

javascriptshort-circuiting

提问by GibboK

I would like to know if JavaScript has "short-circuit" evaluation like && Operator in C#. If not, I would like to know if there is a workaround that makes sense to adopt.

我想知道 JavaScript 是否有像 C# 中的 && 运算符这样的“短路”评估。如果没有,我想知道是否有一种可行的解决方法可以采用。

回答by gdoron is supporting Monica

Yes, JavaScript has "short-circuit" evaluation.

是的,JavaScript 有“短路”评估。

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

Live DEMO

现场演示

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

Live DEMO

现场演示

回答by Rawrplus

This answer goes into great detail on how short-circuitingworks in JavaScript, with all the gotcha's and also relevant themes such as operator precedence, if you're looking for a quick definition and already understand how short-circuiting works, I'd recommending checking other answers.

这个答案非常详细地介绍了JavaScript 中的短路如何工作,以及所有问题和相关主题,例如运算符优先级,如果您正在寻找快速定义并且已经了解短路的工作原理,我会推荐检查其他答案。



What we (thought we) knew so far:

到目前为止我们(认为我们)知道的:

First let's inspect the behaviour we are all familiar with, inside the if()block, where we use &&to check whether the two things are true:

首先让我们检查一下我们都熟悉的行为,在if()块内部,我们&&用来检查这两件事是否是true

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

Now, your first instinct is probably to say: 'Ah yes, quite simple, the code executes the statement if both expr1and expr2are evaluated as true'

现在,你的第一反应可能是说:“是啊,很简单,代码执行,如果双方的陈述expr1expr2被评估为true

Well, yes and no. You are technically correct, that is the behaviour you described, but that's not exactly how the code is evaluatedand we'll need to delve deeper in order to fully understand.

嗯,是和不是。您在技术上是正确的,这就是您所描述的行为,但这并不是评估代码的方式,我们需要深入研究才能完全理解。



How exactly is the &&and ||interpreted?:

&&和究竟是如何||解释的?:

It's time to look "under the hood of the javascriptengine". Let's consider this practical example:

是时候看看“ JavaScript引擎的底层”了。让我们考虑这个实际例子:

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);

Well the result is 260.. but why? In order to get the answer, we need to understand how does the short-circuit evaluation work.

结果是260.. 但为什么呢?为了得到答案,我们需要了解短路评估是如何工作的。

By the MDN Definitionthe &&operator in expr1 && expr2is executed followingly:

If expr1can be converted to true, returns expr2; else, returns expr1.

根据MDN 定义&&操作符expr1 && expr2执行如下:

如果expr1可以转换为true,则返回expr2;否则,返回expr1

So this means, in our practical example, the const resis evaluated the following way:

因此,这意味着,在我们的实际示例中,const res按以下方式评估 :

  1. Invoking expr1- sanitise(0xFF)
  2. 0xFFis a valid hexadecimal number for 250, otherwise I'd return NaN
  3. The expr1returned a "truthy" value, time to execute expr2(otherwise I'd stop as NaNis falsy)
  4. Since userinputis truthy (a number), I can add +5to it
  1. 调用expr1-sanitise(0xFF)
  2. 0xFF是 250 的有效十六进制数,否则我会返回 NaN
  3. expr1返回“truthy”值,执行时间expr2(否则我会停止为NaN是falsy)
  4. 由于userinput是真的(一个数字),我可以添加+5
  • "Truthy" means that expression can be evaluated as true. Here's a list of truthyand falsyexpressions.
  • “Truthy”意味着表达式可以被评估为真。这是一个truthyfalsy表达式的列表 。

So here, we were able to avoid additional ifblocks and further isNaNchecks with a simple usage of the &&operator.

所以在这里,我们能够通过简单的操作符使用来避免额外的if块和进一步的isNaN检查&&



How it really works:

它是如何工作的:

By now, we should at least have a picture how the short-circuitoperators work. The universal rule goes:

到现在为止,我们至少应该了解短路运算符的工作原理。通用规则是:

  • (some falsy expression) && exprwill evaluate to falsy expression
  • (some truthy expression) || exprwill evaluate to truthy expression
  • (some falsy expression) && expr将评估为假表达式
  • (some truthy expression) || expr将评估为真实表达

Here are some further examples for better comprehension:

以下是一些进一步的示例,以便更好地理解:

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');`
*/



One last pesky, but very important thing [Operator Precedence]:

最后一件讨厌但非常重要的事情[运算符优先级]:

Nice, hopefully you're getting the hang of it! Last thing we need to know is a rule about operator precedence, that is:

很好,希望你能掌握它!我们需要知道的最后一件事是关于运算符优先级的规则,即:

  • The &&operator is always executed prior to the ||operator.
  • &&运营商总是先于执行的||操作。

Consider the following example:

考虑以下示例:

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

This will return as, perhaps confusingly to some as a(). Reason is quite simple, it's just our eye-sight that's kind of deceiving us, because we're used to reading left-to-right. Let's take the console.log()and what not out and focus purely on the evaluation

这将返回 as,对于某些 as 可能会造成混淆a()。原因很简单,只是我们的视力在欺骗我们,因为我们习惯于从左到右阅读。让我们把console.log()什么和什么都去掉,只专注于评估

true || false && false

Now to wrap your head around this:

现在让你的头脑围绕这个:

  1. We said the &&operator has precedence, so it gets evaluated as first. To help us better imagine the evaluation, think of the definition

    expr1 && expr2
    

    Where:

    • expr2is false
    • expr1is true || false
  2. So that was the tricky part, now true || falseis evaluated (the expr1- left-side of the &&).

    • Given the ||operator stops execution if expr1 || expr2in expr1evaluates as truthy, the expr1is executed and code execution stops.
  3. The returned value is true

  1. 我们说&&操作符有优先权,所以它被评估为第一个。为了帮助我们更好地想象评估,想想定义

    expr1 && expr2
    

    在哪里:

    • expr2false
    • expr1true || false
  2. 所以这是棘手的部分,现在true || false进行评估(expr1- 的左侧&&)。

    • ||如果expr1 || expr2inexpr1评估为真,则运算符停止执行,expr1则执行 并且代码执行停止。
  3. 返回值为 true

Well.. that was pretty tricky, all because of few weird rules and semantics. But remember, you can always escape operator precedence with the ()- just like in math

嗯..这很棘手,因为很少有奇怪的规则和语义。但是请记住,您始终可以使用()-来逃避运算符优先级,就像在数学中一样

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()  
*/