js赋值语句执行,在有函数的情况下执行顺序究竟是怎样的?

偶然看到这篇文章运算数的求值顺序,里面举了三个例子说明“当函数有副作用的时候,运算数的求值顺序不同会导致结果不同”

但是在运算符优先级表里面可以看到:
函数调用(19,从左到右)>加法(13,从左到右)>赋值(3,从右到左)

请问为什么存在顺序问题?不是应该先执行函数调用,再执行加法吗?

文章中的例子如下:

代码1

var a = 5;
function fun(){
    a = 10;
    return 20;
}
var b = a + fun();
console.log('a:', a);
console.log('b:', b);
// a: 10
// b: 25

代码2

// 交换 a 和 fun 的位置
var a = 5;
function fun(){
    a = 10;
    return 20;
}
var b = fun() + a;
console.log('a:', a);
console.log('b:', b);
// a: 10
// b: 30

代码3

// 让 fun 接收参数
var a = 5;
function fun(a){
    a = 10;
    return 20;
}
var b = fun(a) + a;
console.log('a:', a);
console.log('b:', b);
// a: 5
// b: 25
// var b = a + fun(a); 也能得到一样的结果


补充一下
从加法运算符的结核性来说,是先确定左值再确定右值。
但与关于结核性的解释是这样的:结合性决定了拥有相同优先级的运算符的执行顺序。
所以应该是先考虑优先级,再考虑结核性吧?还是我的理解有误?

不好意思,废话太多了。重复一下我的问题:
请问为什么“代码1”和“代码2”存在顺序问题?不是应该先执行函数调用,再执行加法吗?

阅读 3.9k
2 个回答

可以参考 ECMAScript 5.1 规范:
英文版:http://www.ecma-international...

附录D中有说明:

11.8.2,11.8.3,11.8.5:ECMAScript 总体上是以从左到右的顺序解释执行,但是第 3 版规范中 > 和 <= 运算符的描述语言导致了局部从右到左的顺序。本规范已经更正了这些运算符,现在完全是从左到右的顺序解释执行。然而,这个对顺序的修改,如果在解释执行过程期间产生副作用,就有可能被观察到。

ECMAScript 中所有代码均为从左到右进行执行(评估顺序 evaluation order) ,如果你的函数中有副作用时,例如问题中的代码,则可以明确观察到“从左到右”。

关于运算符优先级与评估顺序的问题,stack overflow上有一个解释的很好:
https://stackoverflow.com/que...

Mark Lutton的回答中提到的问题:
运算符优先级和评估顺序是2个不同的概念,sqrt(9) + sqrt(16) * sqrt(25) 中乘法先运行时错误的,表达式总是从左到右运行,只是遇到 * 运算符时,会优先结合。

所以上述问题中,不管 a + fun() 还是 fun() + a 都只代表 fun() 先结合,而非先运算。

在加法运算时,会先确定左值,再确定右值。

所以,代码1中,确定左值时,a=5,语句可以理解为 var b = 5 + fun(); 之后 fun() 运算,a 变成了 10 , return 20 , 所以 var b = 5 + 20 ; 但 a 在 fun() 运算时已经变成了 10 , b 是 25 。

代码2中,确定左值时,fun() return 20 ,a 变成了 10,之后确定右值,a 已经是 10 了,所以相当于 20 + 10 = 30

代码3中,fun(a) 的参数 a 和 外部变量 a 并不是同一个 a,参数 a 是一个新的变量(参考 js call by value), fun(a) + a 的右值 a 并不会被左边的 fun(a) 影响,所以是: 20 + 5 / 5 + 20

JS语法的顺序跟其他的不一样,并不是从上至下或者从左到右,而是从最简单的语句开始执行

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题