[JS基础]运算符优先级及运算顺序

不知什么时候形成一种认识:运算符的优先级越高就越先执行,前两天在群里写了段代码:

var a =1;
function fn(){alert(a);}
var b = a++ + fn();

alert出的值是是怎么呢?

按照我之前的认识应该是 1,()优先级最高最先被执行此时a=1,可事实在各个浏览器都是 2

不得不怀疑之前的认识

又测试了下其他语言, php,java也都一样的结果:2,c和c++输出:1

参考了下犀牛书还有语言的官方,基本都表述:运算符优先级决定被运算的顺序,像MDN:“Operator precedence determines the order in which operators are evaluated”,但 PHP :“The precedence of an operator specifies how “tightly” it binds two expressions together”。

按php的说法就很好理解上面的问题了,优先级表示着运算符结合能力的强弱

但是真是那些说 “evaluate order”的错了???咨询了好几个同事,终于算是有个自己满意的解释

表达式的运算顺序和运算符优先级根本是两个概念:运算符的优先级只表示着对于运算时哪个运算符先被结合(也可以说执行),至于怎么个顺序运算和它无关,而表达式的运算顺序和各个语言的规范有关,比如java中就明确定义evaluate order:Left To Right,看了下JS的ECAM规范,虽然没用像java那么明确说明运算顺序,但是跟据各个运算符的运算顺序可以看出也是 从左向右 运算的(包括函数调用,参数计算)。

上面 b = a++ + fn()运算过程:

1.运算b是个ref
2.运算=右边部分,a++,此时a=2
3.运算fn()

具体过程可以这样理解:

1.扫描到=操作符,先运算b
2.扫描到++(尽可能多的结合),后面是+,++的优先级高于+,运算a++,此时a++会产生副作用(a+=1),js会先算完子表达式再执行,a=2
3.接着扫描到()执行函数运算

C语言又怎吗输出1呢?

C语言可能为了编译器可以灵活的优化程序,并没用明确确定运算顺序以及副作用处理,所以不同编译器运算结果也可能不同,比如:

int i =1;
int m = (i++) +(i++)+(i++)

有的编译器是6,有的编译器(MSC,TurboC)编译出来是3;还有函数实参运算顺序的问题也一样。

总之:

表达式的运算顺序由语言规范定义和运算符的优先级“无关”,运算符的优先级及结合性只在运算时判断那个运算符先被运算(这样说,MDN的解释也没错只是自己理解错了),更好理解些优先级结合性表示运算符谁先被结合使用;Javascript中 跟据ECAM中对各个操作符的运算顺序的规范,Javascript的运算顺序应该是:从左到右,副作用运算先执行再继续表达式运算(不知有没有特例,没看到明确说明,-_-)

相关的讨论:

JavaEye关于java和c运算顺序的问答:http://www.iteye.com/problems/20258
StackOverflow Javascript运算顺序的讨论: http://stackoverflow.com/questions/5944593/javascript-evaluation-order
一篇讨论c#,java,c运算顺序的blog:http://rednaxelafx.iteye.com/blog/132187 //added 2011-07-13

发表于:2011/07/13 12:47 | 147 views | 发表评论

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

回顶部