我来尝试回答一下楼主的疑问吧。
首先,总结一下楼主的意思是:从规范的语法上看一元运算符前缀无限多个,可是为什么1+ + + + +2可以执行,而++3或者++ ++a又或者--a--等就会报错呢?如果是,那我觉得
@winter可能误会你的疑问了;如果不是,那就折叠我吧。
然后,我核心的答案是:
从
ECMAScript Language Specification的语法上看,UnaryExpression可以是PostfixExpression也可以是operator+UnaryExpression,所以推论出“一元表达式可以作为前缀无限多个”(楼主是想说“一元操作符可以作为前缀无限多个”),貌似比较合理。但是,如果我们详细看每一个operator就会发现不同的operator有不同的执行过程。比如+,我们看“UnaryExpression :+ UnaryExpression”产生式的执行过程非常简单,就是一个ToNumber(GetValue(expr)),在我们正常使用的情况下会按照
Annotated ES5得到一个数字(值,非引用),所以再次对一个值进行+操作的时候,无论是ToNumber还是GetValue都是不会有异常的;而我们去看一下++(Prefix Increment Operator,它就复杂一些了,与我们本次讨论息息相关的是第1、5和6步,首先第一次使用++,通过6步(Return newValue)并追溯newValue(newValue源于ToNumber(GetValue(expr))之后经过第4步获得的),我们获得的表达式的结果是值,而不是引用。然后,当第二次对第一次的结果使用++或者--的时候,通过规范要求的第1步看到首先会将上一次++的结果赋给本次的expr,继续往下走到第五步需要执行PutValue(expr, newValue),这时候的expr已经是一个值,非引用,于是再去PutValue的时候,根据
Annotated ES5的第一步,PutValue (V, W) 的V不是引用的时候,自然就抛出错误了,于是更通俗的说就是“++ UnaryExpression”中的UnaryExpression需要是一个左值表达式。所以,“规范中并没有看到相关的说明”不尽然,只是已经在相关稍微细小的环节说明了。