【问题标题】:How to avoid short-circuited evaluation in JavaScript?如何避免 JavaScript 中的短路评估?
【发布时间】:2016-05-08 03:48:34
【问题描述】:

我需要执行&& 语句的两边,但如果第一部分返回false,则不会发生这种情况。示例:

function doSomething(x) {
    console.log(x);
}

function checkSomething(x) {
    var not1 = x !== 1;
    if (not1) doSomething(x);

    return not1;
}

function checkAll() {
    return checkSomething(1)
        && checkSomething(3)
        && checkSomething(6)
}

var allValid = checkAll(); // Logs nothing, returns false

这里的问题是doSomething(x)应该记录3和6,但是因为checkSomething(1)返回false,其他的检查不会被调用。 运行所有检查并返回结果的最简单方法是什么?

我知道我可以将所有值保存在变量中并随后检查它们,但是当我进行大量检查时,这看起来不是很干净。我正在寻找替代品。

【问题讨论】:

  • I know I could save all the values in variables and check those subsequently 你已经知道答案了,不幸的是它不像你说的那么漂亮。
  • 为什么需要知道所有检查的结果? return 语句不是暗示你想知道 all 检查是否返回true?然后你也不需要评估所有的检查......如果你想单独获得每个检查的结果,那么使用来自 A.Wolff 的数组文字的建议。
  • 您的checkSomething 同时处理两个单独的任务,这通常是不好的做法,会导致这样的问题。根据实际用例,如果 doSomething 必须运行两次,您应该单独执行该任务,而不是依赖它作为 checkSomething 的一致副作用。
  • 短路的一点是,一旦知道逻辑表达式的结果,表达式的以下部分将不会改变结果,所以为什么要运行它们。你不是这样吗?所以,一旦你找到一个false 值,三个&& 操作的整体结果永远不会是true,那么为什么要执行它们呢?除非你在表达式的那些部分有副作用(这是一种邪恶的编码方式)。修复你的代码,而不是用这种方式编写代码。
  • 不,它肯定会解决这个问题。您不需要为每个返回值使用一个变量,您只需要一个标志来检查其中至少一个是否返回 false。

标签: javascript if-statement design-patterns boolean


【解决方案1】:

使用单个 &。那是按位运算符。它将执行所有条件,然后返回结果的按位和。

 function checkAll() {
    return checkSomething(1)
      & checkSomething(2)
      & checkSomething(3)
 }

【讨论】:

  • 这将返回10,而不是truefalse,但这似乎是一个富有成效的方向。
  • return !!(checkSomething(1) & checkSomething(2) & checkSomething(3)) 获取布尔值
  • 更好return !!(checkSomething(1) | checkSomething(2) | checkSomething(3))
【解决方案2】:

您可以将比较结果相乘并将其转换为布尔值。

function checkSomething(x) {
    var not1 = x !== 1;
    if (not1) alert(x);
    return not1;
}

function checkAll() {
    return !!(checkSomething(1) * checkSomething(2) * checkSomething(3));
}

document.write(checkAll());

或者采取一些数组方法:

function checkAll() {
    return [checkSomething(2), checkSomething(2), checkSomething(3)].every(Boolean);
}

【讨论】:

  • 既然可以使用& 运算符,为什么还要乘法?这样它仍然会读作“某物和某物和某物”......
  • 然后使用按位或|
  • 数组方法最适合我,TypeScript 似乎不喜欢其他方法
【解决方案3】:

2.5 年后回到我自己的问题,我同意 cmets 中的人的观点,即基于副作用的代码有多糟糕,因此违反了单一责任原则。

我只想为访问此页面的人提供一个适当的解决方案。

function doSomething(x) {
    console.log(x);
}

function checkSomething(x) {
    return x !== 1;
}

var values = [1, 3, 6];
var validValues = values.filter(checkSomething); // -> [3, 6]

validValues.forEach(doSomething); // -> Logs 3 and 6
var allValid = validValues.length === values.length; // false

如您所见,checkSomething 函数现在只做一件事:检查。 doSomething 逻辑所有检查完成后单独运行。

函数应该总是做某事返回某事,而不是两者兼而有之。当然,这也有例外,但这是一个很好的经验法则。这使得代码更加可预测、可测试和易于理解。

现在,如果我想在不“做某事”的情况下检查所有值是否有效,我实际上可以这样做......

var allValid = checkSomething(1) && checkSomething(3) && checkSomething(6);

...无需担心副作用。

结论:你不想避免短路评估

【讨论】:

    猜你喜欢
    • 2010-10-03
    • 1970-01-01
    • 2014-07-06
    • 2011-03-15
    • 2015-05-11
    • 2021-09-23
    相关资源
    最近更新 更多