JavaScript有"短路"评估吗?

Gib*_*boK 90 javascript short-circuiting

可能重复:
使用&&的短路作为if语句?
javascript是否在布尔表达式中使用优化?

我想知道是否__CODE__"短路"评估,如C#中的&& Operator.如果不是,我想知道是否有采用合理的解决方法.

gdo*_*ica 105

是的,JavaScript有"短路"评估.

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

现场演示

if (false && foo.foo){
    // Passes, no errors because foo isn't defined.
}
Run Code Online (Sandbox Code Playgroud)

现场演示

  • 如此短路它是JS的标准? (6认同)
  • @GibboK.标准中的是!但是好的评论,就像Javascript编译 - javascript实现中的魔术一样,人们真的想知道某些东西是"标准",还是可能受制于实施.评估二元逻辑运算符的条件语句的方式,并且(short-curcuit)是标准行为http://www.ecma-international.org/ecma-262/5.1/#sec-11.11 (4认同)
  • @GibboK:查看[运营商参考](https://developer.mozilla.org/en-US/learn/javascript).是的,JS中也有一个二元AND运算符. (2认同)

Raw*_*lus 9

如果您正在寻找一个快速的定义并且已经了解短路的工作原理,那么这个答案将详细介绍在JavaScript中的工作方式,所有陷阱以及相关主题(例如运算符优先级)。检查其他答案。


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

首先,让我们在if()块中检查我们熟悉的行为,在其中&&检查两件事是否是true

if (true && true) {
   console.log('bar');
} 
Run Code Online (Sandbox Code Playgroud)

现在,您的第一个本能可能是说:“是的,很简单,如果代码同时执行expr1expr2被评估为true'

好,是的,不是。从技术上来说,您是正确的,这就是您描述的行为,但这并不完全是对代码进行评估的方式,我们需要更深入地研究才能完全理解。


&&和的确切||解释是:

现在该看看“在引擎的 ”了。让我们考虑这个实际的例子:

if (true && true) {
   console.log('bar');
} 
Run Code Online (Sandbox Code Playgroud)

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

通过MDN定义&&操作符将在expr1 && expr2以下执行:

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

因此,这意味着在我们的实际示例中,将const res通过以下方式对进行评估:

  1. 调用expr1-sanitise(0xFF)
  2. 0xFF 是250的有效十六进制数,否则我将返回 NaN
  3. expr1返回“truthy”值,执行时间expr2 (否则我会停止为NaN是falsy)
  4. 由于userinput是truthy(数字),我可以添加+5到它
  • “ Truthy”表示可以将表达式评估为true。这是真实虚假 表达的清单 。

因此,在这里,我们可以通过简单地使用运算符来避免其他if块并进一步isNaN检查&&


实际运作方式:

到目前为止,我们至少应该操作员的工作方式有所了解。通用规则是:

  • (some falsy expression) && expr 将评估为虚假表达
  • (some truthy expression) || expr 将评估为真实表达

以下是进一步理解的一些示例:

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);
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)


最后一件令人讨厌的但很重要的事情[操作员优先]:

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

  • &&运营商总是先于执行的||操作。

考虑以下示例:

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');`
*/
Run Code Online (Sandbox Code Playgroud)

这将返回,可能会使混淆a()。原因很简单,只是我们的目光在欺骗我们,因为我们习惯于从左到右阅读。让我们拿出console.log()和不拿出什么,而只专注于评估

true || false && false
Run Code Online (Sandbox Code Playgroud)

现在,将您的头缠起来:

  1. 我们说&&运算符具有优先权,因此它首先被评估。为了帮助我们更好地想象评估,请考虑一下定义

    expr1 && expr2
    
    Run Code Online (Sandbox Code Playgroud)

    哪里:

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

    • 给定||运算符,如果expr1 || expr2in expr1评估为“真”,则停止执行,然后expr1执行并停止执行代码。
  3. 返回值是 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());

// returns a() and stops execution
Run Code Online (Sandbox Code Playgroud)

  • 这是我见过的最好的*“未明确回答问题的绝佳答案” * ... (4认同)