有些运算符不直接产生运算效果,而是用于影响运算效果,这一类运算符的操作对象通常是“表达式”,而非“表达式的值”。
看下表:
运算符 | 作用 | 备注 |
---|---|---|
void | 避免表达式返回值 | 使表达式总是返回值undefined |
?: | 表达式分组和调整运算次序 | 也称优先级运算符 |
() | 避免表达式返回值 | 使表达式总是返回值undefined |
, | 表达式顺序地连续执行 | 也称多重求值或条件运算符 |
这四个运算符面向表达式进行运算。其特殊性在于:普通运算符对表达式求值以获得结果,而这4个运算符并不直接对表达值进行求值运算,而是通过操作表达式去影响运算结果。例如,boid运算符,它对其后的表达式的影响就是:避免产生结果
尽管它们是以“表达式”为目标,但语义上它们仍然是运算符。因此它们与运算对象(表达式
)结合的结果仍然是表达式(而非语句)。例如:
void null//void 是运算符,null是运算元:单值表达式
但运算符的后面不能是语句(很显然,这是语法规则),所以下面的代码是不合法的:
//用{}表示的复合语句不能作为void的运算对象
void {
//...
}
那么问题来了,既然void运算的对象是表达式,且JavaScript允许单值表达式,那么这样的代码中:
void 1+2
void运算的对象到底是“1”这个单值表达式,还是“1+2”这个算术表达式呢?
如果是第一种情况,那么结果如上图所示
如果是第二种情况,那么结果如上图所示
这就涉及两个例子中表达式1的运算符”void
“和表达式2中的运算符”+
“的优先级的问题了:谁的运算优先级更高,则先以该运算符来构成表达式并完成运算。在JavaScript中,该优先级顺序如下(序数越小,越优先运算):
JavaScript中运算符的优先级
序号 | 运算符 | 描述 |
---|---|---|
1 | . [] () | 对象成员存取,数组下标,函数调用等 |
2 | ++ - ~ ! delete new typeof void | 一元运算符等 |
3 | * / % | 乘法 除法 取模 |
4 | + - + | 加法,减法,字符串连接 |
5 | « » »> | 移位 |
6 | < <= > >= instanceof | 序列检测,instanceof |
7 | == != === !== | 等值检测 |
8 | & | 按位与 |
9 | ^ | 按位异或 |
10 | | | 按位或 |
11 | && | 逻辑与 |
12 | || | 逻辑或 |
13 | ?: | 条件 |
14 | = op= | 赋值,运算赋值 |
15 | , | 多重求值 |
通过该优先级表可知:由于”void”运算符高于”+”运算符,因此应该以上述的第一种情况进行运算,其结果值为NaN
因此如果希望以第二种情况进行运算,就需要使用强制运算符”()”来改变执行(优先级别的)顺序。下面的代码实现第二种情况的运算效果
void (1+2)
正如我们留意到的:在”void”与”()”参与的这几个运算中,运算符并不对值进行运算,而是对表达式(包括单值表达式
)的运算效果进行影响。所以我们一再强调,”void”与”()”等这些运算符的运算对象,是“表达式”而非变量/值运算元。
参考资料《JavaScript语言精髓和编程实践》