【问题标题】:Why is JavaScript's post-increment operator different from C and Perl?为什么 JavaScript 的后自增运算符与 C 和 Perl 不同?
【发布时间】:2010-02-14 22:28:52
【问题描述】:

我现在正在准备 JavaScript 考试。我对 C 和 Perl 也有一点了解,所以我熟悉所有三种语言的前缀和后缀运算符。

我为它进行了在线练习考试,我犯的一个错误是在评估以下代码时:

var x = 10;
x += x--;

现在,我认为它会计算为 19,因为它是 10 + 10,然后减去 1 得到 9。但我得到的反馈是它是错误的,它实际上计算为 20。我觉得这听起来有点可疑,所以我在 HTML 文档中对其进行了测试,结果又出现了 20 个。然后我尝试了 C 和 Perl 中的等价物,并且都评估为 19。

谁能向我解释为什么 JavaScript 将答案评估为 20 而其他语言将其评估为 19?我从测试中得到的答案对我来说不是很清楚:

增量 ++ 和递减 - 可以放置运算符 在操作数之前或之后。如果增加或减少 运算符放在操作数之前,操作立即发生。 如果将递增或递减运算符放在操作数之后,则 操作数值的变化直到下一次 在程序中访问操作数。因此表达式 x += x-- 等价于 x = x + 10 计算为 20。

【问题讨论】:

  • 啊,我多么讨厌这种愚蠢的“陷阱”问题!后缀递增/递减运算符不应该出现在包含另一个对被 (in|de) 递减变量的引用的表达式中。
  • 在 C 中,这是未定义的行为;任何包含这个 sn-p 的代码都被破坏了
  • += 不引入序列点吗?
  • @Anon: 不,它没有——语句的结尾是下一个序列点
  • 啊,有道理。我已经更正了我的那部分答案。

标签: javascript c perl


【解决方案1】:

扩展语句

x += x--;

到更冗长的 JS 代码

x = x + (function(){ var tmp = x; x = x - 1; return tmp; })();

结果非常有意义,因为它会评估为

x = 10 + (function(){ var tmp = 10; x = 10 - 1; return tmp; })();

这是 20。请记住,JS 从左到右计算表达式,包括复合赋值,即 x 的值在执行 x-- 之前被缓存。


你也可以这样想:假设从左到右的求值顺序,JS 将赋值解析为

x := x + x--

而 Perl 将使用

x := x-- + x

我没有看到任何令人信服的论据支持或反对这两种选择,所以不同语言的行为不同只是运气不好。

【讨论】:

  • 谢谢,这使得它相当清楚 - 但它仍然很烦人。我想这是一个陷阱——我想没有人会真正使用这样的代码,除非它被故意混淆!
【解决方案2】:

在 C/C++ 中,每个变量在每个语句中只能更改一次(我认为确切的术语是:两个代码点之间只能更改一次,但我不确定)。

如果你写

x += x--;

您将 x 的值更改两次:

  • 您正在使用后缀 -- 运算符递减 x
  • 您正在使用赋值设置 x 的值

虽然你可以写这个并且编译器不会抱怨它(不确定,你可能想检查不同的警告级别),但结果是未定义的,并且每个编译器都可能不同。

【讨论】:

  • 你要找的词是“sequence point”,和“every statement”有很大的不同。
  • 是的,你是对的,詹姆斯。感谢您指出了这一点。有关 Wikipedia 上序列点的更多信息:en.wikipedia.org/wiki/Sequence_point.
【解决方案3】:

基本上,x 的值在赋值后被递减。这个例子可能会更清楚(在 Firebug 控制台中运行)

var x = y =10;    
x += y--;        
console.log(x , y); // outputs 20 9

【讨论】:

    【解决方案4】:

    在 C 中,行

    x += x--;
    

    是未定义的行为。您的特定编译器似乎将其视为:

    oldx = x--;
    x = x + oldx
    

    然而,ECMAScript 规范确实指定了op= - 并且它在评估右侧之前获取左侧的值。

    所以它相当于:

    oldx = x--;
    x = oldx + oldx
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-26
      • 2012-01-10
      • 1970-01-01
      • 2016-11-25
      • 2018-12-03
      • 2012-03-09
      • 2013-02-23
      • 2011-11-15
      相关资源
      最近更新 更多