【问题标题】:Why does this condition in a while loop get executed as though it were part of the loop body?为什么 while 循环中的这个条件会像循环体的一部分一样被执行?
【发布时间】:2015-12-05 21:03:54
【问题描述】:

下面是相关函数(本例取自here):

​function factorial (num) {
  if (num < 0) {
    return -1;
  }
  else if (num == 0) {
    return 1;
  }
var tmp = num; 
  while (num-- > 2) {
    tmp = tmp * num;
  }
return tmp;
}
console.log(factorial(8));
----> 40320

当我研究这个函数的工作原理时(并且对表达式 (num-- &gt; 2) 中的运算符优先级感到困惑;感谢我在 MakerSquare 的导师 Edwin Calte 指出这一点),我注意到 num 变量甚至递减尽管这种递减是被规定为要执行的循环体的前提条件,并且它本身不是循环体的一部分。我可以理解为什么它会这样做,如果表达式改为:

while (num-- > 2) {
num--;
...}

在上面的例子中,第二个num-- 并不是它工作所必需的。当我在我的 devtools 控制台中运行它时,另一个类似的表达式是:

if (x - 2 == 5) { x-- }

这里,似乎如果 x 为 7,则 x 将减 1,​不是​如果 x 为 7,则从 x 中减去 2,然后 x 将减 1。但是在上面num的例子中,后一个原理才是生效的。

谁能解释一下原因?

【问题讨论】:

  • num--改变num的值
  • 请记住,if/for/while 语句中的括号没有什么特别之处。它的评估与循环体中的代码相同。如果括号表达式返回的值是真值,则条件成功。甚至赋值也是表达式:x = 1 将返回值 1

标签: javascript while-loop conditional-statements


【解决方案1】:

因为每次计算表达式 num-- 时(在循环的每次迭代中查看是否满足条件),它都会将 num 减一。很多 JavaScript 专家会告诉你避免使用 num--num++--num++num,因为它们的副作用不太直观。

我的建议是坚持使用乍一看更易读的内容,即使要输入更多字符。

while (num > 2) {
  num = num - 1;
}

至少,仅将它们用作独立语句以明确它们的工作。

while (num > 2) {
  num--;
}

在第二个带有表达式x - 2 == 5 的示例中,此表达式根本不适用于x;它不会改变它的价值。您不会像在 x-- 时那样将任何内容分配回 xx--; 完全等同于 x = x - 1;。碰巧它还返回了x的值赋值之前;这样它可以用作条件。这就像从一个变量中读取,然后在一个语句中将其全部写入。

【讨论】:

  • 你的后一点是正确的,但我认为这不会影响直观的可读性。
  • 在独立语句中使用时它们是完全可读的。当作为其他表达式的一部分嵌入时,它们可能会造成混淆。
  • 这是真的,但这都是主观的,无论如何都与答案无关。我和我的许多同事都认为,即使作为独立的语句,这些运算符也很笨拙。无论如何,这显然让 OP 感到困惑。
  • @Codorilla 这不是我要说的。我是说没有人认为for (i = 0; i &lt; n; i++) 中的i++ 不可读。但是x++ &lt; 2 可能会令人困惑,因为您将递增与比较相结合。或 C 风格 *p++ = x。其中一些成为习语,但在您习惯之前它们仍然令人困惑。
  • 我想这只是递减/递增运算符的一个怪癖吧?我会在编写代码时听取您的建议。但是当我阅读其他人的代码时,我不得不询问它是否弹出,如上例所示。谢谢。
【解决方案2】:

x - 2 将表示一个新值,即如果您打开控制台并输入x - 2,它将以5 响应,但该值未分配给任何东西(因此x 不受影响)。 --++ 运算符是独立的语句,它们会影响它们所操作的变量。所以你的num-- &gt; 2num &gt; 2 后面跟着num = num - 1 的名称,它比较当前值,然后执行数学运算并将该运算的结果分配给变量。

【讨论】:

  • 你的等价不正确。 num-- 递减变量,但返回旧值,而不是新值。
  • 你不知道x----x的区别吗?
  • 是的,我只是从不在重要的情况下使用它们,所以我将它们混合在一起。
  • 明白我所说的非直觉是什么意思? :P
【解决方案3】:

num-- 做了两件事:它从变量num 中减去1(将结果分配回num),还返回num 的原始值以用于其余的枚举。所以

(num-- > 2)

是:

(temp = num; num = num - 1; temp > 2)

你的while循环可以写成:

while (num > 2) {
    num--;
    tmp = tmp * num;
}

请注意,我在 while 子句中不再有 num--。如果我这样做了,变量将减少两次:一次是在测试条件时,一次是在循环内。

【讨论】:

  • 有趣的是它不是完全相同的东西。如果num 初始化为5,在第二个示例中num 实际上等于2 而在原始示例中它等于1,因为您在比较之前递减,并且在最后一种情况下,您在确定不小于2 之前减少num == 2。在这种情况下,功能上无关紧要,但这是一个很好的潜在陷阱!
  • 好点。在给定的程序中无关紧要,因为它在循环之后不使用num,所以它的最终值是无关紧要的。但它可以在其他一些程序中。
猜你喜欢
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
相关资源
最近更新 更多