首先,我知道后面谈到的表达方式side-effects
,不应该在生产环境中使用.我只想JavaScript
通过他们了解.所有这些都经过测试Chrome
.
var a = 42; var b = "42"; a + ++b; // result is 85
这是我的理解a + ++b
,
根据运算符优先级,Prefix Increment (++)
(优先级15)优先级高于Addition(+)
(优先级13).可以解析VAR 来,请参阅.然后结果可能是.++b
ToNumber(GetValue(expr))
43
12.5.7 Prefix Increment Operator
a + 43
85
然而,
var a = 42; var b = "42"; a++ + b; // "4242"
为什么结果a++ + b
是"4242"
?
我试着理解结果"4242"
,似乎首先a++
返回42
,然后是42 + '42'
,首先42
是'42'
var ToString()
,参考12.7.3 The Addition operator ( + )
.然后结果可能是"4242"
.
但它似乎违反了规则:( Postfix increment
优先级16)高于Addition
(优先级13)???
var a = 42; var b = "42"; a +++b; // "4242"
如何a +++b;
解析?
哈哈,狡猾的!
修复后增量返回相同的值,然后递增变量.这是我所知道的每种语言的默认行为.
所以,当你这样做时(警告:这不是一个有效的表达式,只是为了表明这个想法):
42++ + "42"
真正发生的是:
++运算符返回第42个
然后42增加到43
然后将42(表达式的结果值)强制转换为字符串
然后将两个操作数连接起来
编辑#1:
如果你这样做:
var a = 42; var b = "42"; a + b++; // result is 84
测试一下!
编辑#2:
因此,我们总结您的问题与运算符优先级无关(:
javascript和其他语言的post和pre增量有所不同.也就是说,这些运算符可以与操作数中的单个空格分开.例如:
var a = 42; ++ a;
注意++和a之间的空间,这也适用于a ++
当javascript开始解析语句时它需要操作数或运算符并将其存储在其堆栈中并找到任何机会使用它.我希望你知道语言如何解析语句,从左到右或从右到左.Javascript从左到右解析它.
所以,当你写a +++b
它开始从左边解析时,
找到了:推进堆叠; stack:[a]
Found +:push + in stack; stack:[a,+]
找到+:pop +和一个来自堆栈并应用操作数并将结果推送到堆栈上(现在堆栈只有一个内存,而不是一个++,因为后增量); stack [a]
Found +:push on stack; stack:[a,+]
找到b:pop +和一个来自堆栈,应用操作数并将结果推送到堆栈; 堆栈:[b]
没有更多的操作数或运算符,所以它给出了结果,a+b
并且在a之后增加a作为a后增量的结果,如果你想在添加之前增加b,你可以试试这个:
a + ++b
这将分离+ ++,现在javascript知道应用增量的位置.
当然,递增/递减运算符 - 作为一元运算符 - 优先于+
(加法/连接)二元运算符,但我认为这里的问题是强制.让我解释:
为什么++ + b的结果是4242?
(a
是一个数字42,b
是一个字符串'42')
这是因为当您将increment
运算符应用于具有数字值('42')的字符串时,结果将强制转换为数字(42).
所以现在我们留下一个表达式number + string
(42 + '42'):在这种情况下,+
运算符将连接(将数字42强制转换为字符串'42'并产生字符串'4242').
另一方面:在第一个例子中a + ++b
(a
是数字42并且b
是字符串'42') - b
在增量之后将被强制转换为数字number + number
(42 + 43) - 因此+
运算符将执行addition
而不是连接(42 + 43 = 85)
关于下一个问题:
a +++ b怎么样; 被解析?
由于将变量和增量操作符与空格分开是合法的,因此解析器将查看a +++b
并首先查看a++
.
此外,由于+
运营商不两个操作数之间需要空间,解析器会分开两个操作数a++
和b
正确地与+
运营商.因此a +++b;
将被解析为a++ + b
@zangw没有什么比++有更高的优先级而不是+.++ b是一个预增量运算符,+是一个算术.++ b意味着首先改变一个操作数的值,然后使用它与++相矛盾.++总是带有一个操作数,+来自两个操作数,后者是一个操作.希望你明白了吗?