有些运算符不直接产生运算效果,而是用于影响运算效果,这一类运算符的操作对象通常是“表达式”,而非“表达式的值”。

看下表:

运算符 作用 备注
void 避免表达式返回值 使表达式总是返回值undefined
?: 表达式分组和调整运算次序 也称优先级运算符
() 避免表达式返回值 使表达式总是返回值undefined
, 表达式顺序地连续执行 也称多重求值或条件运算符

这四个运算符面向表达式进行运算。其特殊性在于:普通运算符对表达式求值以获得结果,而这4个运算符并不直接对表达值进行求值运算,而是通过操作表达式去影响运算结果。例如,boid运算符,它对其后的表达式的影响就是:避免产生结果

尽管它们是以“表达式”为目标,但语义上它们仍然是运算符。因此它们与运算对象(表达式)结合的结果仍然是表达式(而非语句)。例如:

    void null//void 是运算符,null是运算元:单值表达式

但运算符的后面不能是语句(很显然,这是语法规则),所以下面的代码是不合法的:

    //用{}表示的复合语句不能作为void的运算对象
    void {
    	//...
    }

那么问题来了,既然void运算的对象是表达式,且JavaScript允许单值表达式,那么这样的代码中:

void 1+2

void运算的对象到底是“1”这个单值表达式,还是“1+2”这个算术表达式呢?

img

如果是第一种情况,那么结果如上图所示

img

如果是第二种情况,那么结果如上图所示

这就涉及两个例子中表达式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语言精髓和编程实践》