这个答案非常详细地介绍了 short-circuiting 在 JavaScript 中的工作原理,以及所有的问题和相关的主题,例如运算符优先级,如果您正在寻找一个快速定义并且已经了解短路的方式有效,我建议检查其他答案。
到目前为止我们(认为我们)知道的:
首先让我们检查一下我们都熟悉的行为,在if() 块内,我们使用&& 来检查这两个东西是否是true:
if (true && true) {
console.log('bar');
}
现在,你的第一反应可能是:'是的,很简单,如果expr1 和expr2 都被评估为true' p>
嗯,是的,也不是。您在技术上是正确的,这就是您描述的行为,但这并不是代码的确切评估方式,我们需要更深入地研究才能完全理解。
&& 和 || 究竟是如何解释的?:
是时候看看“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);
结果是260.. 但是为什么呢?为了得到答案,我们需要了解短路评估是如何工作的。
MDN
Definition
expr1 && expr2 中的 && 运算符执行如下:
如果expr1可以转换为true,则返回expr2;否则,返回expr1。
这意味着,在我们的实际示例中,const res 的评估方式如下:
- 调用
expr1 - sanitise(0xFF)
-
0xFF 是 250 的有效十六进制数,否则我会返回 NaN
-
expr1 返回一个“真实”值,是时候执行expr2 (否则我会停下来,因为NaN 是假的)
- 由于
userinput 是真实的(一个数字),我可以添加+5 到它
因此,在这里,我们能够通过简单地使用 && 运算符来避免额外的 if 块和进一步的 isNaN 检查。
它是如何工作的:
到目前为止,我们至少应该了解short-circuit 运算符的工作原理。通用规则是:
(some falsy expression) && expr 将评估为假表达式
(some truthy expression) || expr 将评估为真实表达式
这里有一些进一步的例子可以更好地理解:
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');`
*/
最后一个令人讨厌但非常重要的事情[运算符优先级]:
很好,希望你能掌握它!我们需要知道的最后一件事是关于运算符优先级的规则,即:
&& 运算符始终在 || 运算符之前执行。
考虑以下示例:
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
这将返回为a(),可能会让某些人感到困惑。原因很简单,只是我们的视力有点欺骗我们,因为我们习惯于从左到右阅读。让我们把console.log() 和其他没有的东西拿出来,只关注评估
true || false && false
现在开始讨论这个问题:
-
我们说&& 运算符具有优先级,因此它首先被评估。为了帮助我们更好地想象评估,想想定义
expr1 && expr2
地点:
-
expr2 是 false
-
expr1 是 true || false
-
所以这是棘手的部分,现在 true || false 被评估(expr1 - && 的左侧)。
- 假设
|| 运算符停止执行,如果 expr1 中的 expr1 || expr2 评估为真,则执行 expr1 并停止代码执行。
返回值为true
嗯.. 这很棘手,都是因为很少有奇怪的规则和语义。但请记住,您始终可以使用 () 转义运算符优先级 - 就像在数学中一样
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()
*/