2010-02-14 61 views
6

我正在学习关于JavaScript的考试。我也对C和Perl有了一些了解,所以我熟悉所有三种语言的前缀和后缀表示法。为什么JavaScript的后缀表示法与C和Perl不同?

我做了一个在线模拟考试吧和一个错误,我做了评估下面的代码:

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

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

任何人都可以向我解释为什么JavaScript在20其他语言将其评估为19时评估答案为20?我从测试得到的回答却不太清楚对我说:

增量++ 和递减 - 运营商可以放置 之前或之后的操作数。如果将运算符的增量或减量运算放在操作数之前,则操作立即发生。 如果递增或递减操作符位于操作数之后,则操作数值的更改直到下一次在程序中访问操作数 才会显现。因此表达式x + = x--相当于X = X + 10,其结果为20

+3

啊,我怎么讨厌这种愚蠢的“疑难杂症”的问题!后缀增量/减量运算符不应该出现在包含另一个变量引用(in | de)的表达式中。在C中为 – 2010-02-14 22:33:44

+6

,这是未定义的行为;包含这段代码的任何代码都是固有的破坏 – Christoph 2010-02-14 22:34:23

+0

'+ ='没有引入序列点吗? – 2010-02-14 22:47:41

回答

6

扩大声明

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 

我不没有看到任何有说服力的论据支持或反对任何一种选择,所以不同语言的行为有所不同。

+1

谢谢,这使得它相当清楚 - 但它仍然令人讨厌。我猜这是作为一个陷阱 - 我想象没有人会真的使用这样的代码,除非它被故意混淆! – 2010-02-14 23:50:24

3

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

如果你写

x += x--; 

你改变x的值的两倍:

  • 您正在使用的后缀递减X - 运营商
  • 您使用设置x的值作业

尽管你可以写这个,编译器也不会抱怨关于它(不确定,你可能想检查不同的警告级别),结果是未定义的,并且在每个编译器中可能不同。

+2

您正在寻找的术语是“序列点”,与“每个语句”有很大不同。 – jamesdlin 2010-02-14 23:27:32

+0

是的,你是对的詹姆斯。感谢您指出了这一点。更多关于维基百科序列点的信息:http://en.wikipedia.org/wiki/Sequence_point。 – Patrick 2010-02-14 23:29:25

1

在C中,线

x += x--; 

是未定义的行为。这似乎是你的特定编译器处理它想:

oldx = x--; 
x = x + oldx 

但是,ECMAScript规范指定op= - 它之前得到左手侧的价值评估右手工侧。

oldx = x--; 
x = oldx + oldx 
1

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

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