结合性

左结合:相当于把左边的子表达式加上小括号
右结合:相当于把右边的子表达式加上小括号

1
2
3
3+10*2 // 23
(3+10)*2 // 26 -> 左结合
3+(10*2) // 23 这里的括号是多余的 -> 右结合

赋值运算符是右结合的,所以可以像下面这样写

1
a = b = 5 // 相当于 a = ( b = 5 )

分组和短路
下表中,分组具有最高优先级,然而,这并不意味着总是优先对分组内的表达式进行求值,尤其是涉及短路时

常见短路例子如下:

代码示例 说明
a || (b * c) 首先对 a 求值,如果 a 为真值则直接返回 a
a && (b < c) 首先对 a 求值,如果 a 为虚值则直接返回 a
a ?? (b || c) 首先对 a 求值,如果 a 不是 null 或 undefined 则直接返回 a
a?.b.c 首先对 a 求值,如果 a 是 null 或 undefined 则直接返回 undefined
1
2
3 > 2 && 2 > 1 // true
3 > 2 > 1 // false -> 3>2是true,tru在比较中会被隐式转换为1,1>1,结果是 false

汇总表

优先级 运算符类型 结合性 运算符
19 分组 ( )小括号
18 成员访问 从左到右 . 英文点,比如 obj.a
需计算的成员访问 从左到右 比如 obj[a]
new(带参数) new ...(...),比如:new Number(1)
函数调用 从左到右 function()
可选链 从左到右 ?.
17 new (无参数) 从右到左 new ……
16 后置递增 ···++,比如:2++
后置递减 ···--,比如:2--
15 逻辑非 从右到左 !……,即取反
按位非 ~···
一元加法 +···,比如:+2
一元减法 -··,比如:-2
前置递增 ++···,比如:++2
前置递减 --···,比如:--2
typeof typeof ···
void void ···
delete delete ···
await await ···
14 从右到左 ··· **···,比如2的3次方,2**3
13 乘法 从左到右 ··· * ···
除法 ··· / ···
取余 ··· % ···
12 加法 从左到右 ··· + ···
减法 ··· - ···
11 按位左移 从左到右 ··· << ···
按位右移 ··· >> ···
无符号右移 ··· >>> ···
10 小于 从左到右 ··· < ···
小于等于 ··· <= ···
大于 ··· > ···
大于等于 ··· >= ···
in ··· in ···
instanceof ··· instanceof ···
9 相等 从左到右 ··· == ···
不相等 ··· != ···
全等 ··· === ···
不全等 ··· !== ···
8 按位与 从左到右 ··· & ···
7 按位异或 从左到右 ··· ^ ···
6 按位或 从左到右 ··· | ···
5 逻辑与 从左到右 ··· && ···
4 逻辑或 从左到右 ··· || ···
空值合并 从左到右 ··· ?? ···
3 三元运算符 从右到左 ··· ? ··· : ···
2 赋值 从右到左 ··· = ···
··· += ···
··· -= ···
··· **= ···
··· *= ···
··· /= ···
··· %= ···
··· <<= ···
··· >>= ···
··· >>>= ···
··· &= ···
··· ~= ···
··· |= ···
··· &&= ···
··· ||= ···
··· ??= ···
1 逗号/序列 从左到右 ··· , ···