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
Does JavaScript have "Short-circuit" evaluation?
提问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
回答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 expr1
and expr2
are evaluated as true
'
现在,你的第一反应可能是说:“是啊,很简单,代码执行,如果双方的陈述expr1
和expr2
被评估为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 inexpr1 && expr2
is executed followingly:If
expr1
can be converted totrue
, returnsexpr2
; else, returnsexpr1
.
根据MDN 定义,
&&
操作符expr1 && expr2
执行如下:如果
expr1
可以转换为true
,则返回expr2
;否则,返回expr1
。
So this means, in our practical example, the const res
is evaluated the following way:
因此,这意味着,在我们的实际示例中,const res
按以下方式评估 :
- Invoking
expr1
-sanitise(0xFF)
0xFF
is a valid hexadecimal number for 250, otherwise I'd returnNaN
- The
expr1
returned a "truthy" value, time to executeexpr2
(otherwise I'd stop asNaN
is falsy) - Since
userinput
is truthy (a number), I can add+5
to it
- 调用
expr1
-sanitise(0xFF)
0xFF
是 250 的有效十六进制数,否则我会返回NaN
- 在
expr1
返回“truthy”值,执行时间expr2
(否则我会停止为NaN
是falsy) - 由于
userinput
是真的(一个数字),我可以添加+5
它
So here, we were able to avoid additional if
blocks and further isNaN
checks 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) && expr
will evaluate to falsy expression(some truthy expression) || expr
will 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:
现在让你的头脑围绕这个:
We said the
&&
operator has precedence, so it gets evaluated as first. To help us better imagine the evaluation, think of the definitionexpr1 && expr2
Where:
expr2
isfalse
expr1
istrue || false
So that was the tricky part, now
true || false
is evaluated (theexpr1
- left-side of the&&
).- Given the
||
operator stops execution ifexpr1 || expr2
inexpr1
evaluates as truthy, theexpr1
is executed and code execution stops.
- Given the
The returned value is
true
我们说
&&
操作符有优先权,所以它被评估为第一个。为了帮助我们更好地想象评估,想想定义expr1 && expr2
在哪里:
expr2
是false
expr1
是true || false
所以这是棘手的部分,现在
true || false
进行评估(expr1
- 的左侧&&
)。||
如果expr1 || expr2
inexpr1
评估为真,则运算符停止执行,expr1
则执行 并且代码执行停止。
返回值为
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()
*/