优先级在结合性之前,无论结合性和优先级如何,求值顺序总是从左到右,结合性默认从左到右
| 优先级(高到低) | 运算符名称 | 运算符 | 结合性 | 例子 |
|---|---|---|---|---|
| 19 | 分组 | (…) | - | (a + b) * c |
| 18 | 属性 点访问 | … . … | a.b | |
| 属性 括号访问 | … [ … ] | a[b] | ||
| new 有参 | new … ( … ) | - | new f() | |
| 函数调用 | … ( … ) | f() | ||
| 可选链ES2020 | ?. | a?.b | ||
| 17 | new 无参 | new … | 右到左 | new f |
| 16 | 后置递增 | … ++ | - | a++ |
| 后置递减 | … — | - | a-- | |
| 15 | 逻辑非 | ! | 右到左 | !a |
| 按位非 | ~ | 右到左 | ~a | |
| 一元加 | + | 右到左 | +a | |
| 一元减 | - | 右到左 | -a | |
| 前置递增 | ++ … | 右到左 | ++a | |
| 前置递减 | — … | 右到左 | --a | |
| 取类型 | typeof | 右到左 | typeof a | |
| 计算但是不返回值 | void | 右到左 | void a | |
| 删除对象属性 | delete | 右到左 | delete a.b | |
| 异步等待 | await | 右到左 | await a() | |
| 14 | 幂ES2016 | … ** … | 右到左 | a ** b |
| 13 | 乘法 | … * … | a * b | |
| 除法 | … / … | a / b | ||
| 取余 | … % … | a % b | ||
| 12 | 加法 | … + … | a + b | |
| 减法 | … - … | a - b | ||
| 11 | 按位左移 | … << … | a << b | |
| 按位右移 | … >> … | a >> b | ||
| 无符号右移 | … >>> … | a >>> b | ||
| 10 | 小于 | … < … | a < b | |
| 小于等于 | … ⇐ … | a <= b | ||
| 大于 | … > … | a > b | ||
| 大于等于 | … >= … | a >= b | ||
| 包含 | … in … | a in b | ||
| 原型链判断 | … instanceof … | a instanceof b | ||
| 9 | 相等 | … == … | a == b | |
| 不相等 | … != … | a != b | ||
| 严格相等 | … === … | a === b | ||
| 严格不相等 | … !== … | a !== b | ||
| 8 | 按位与 | … & … | a & b | |
| 7 | 按位异或 | … ^ … | a ^ b | |
| 6 | 按位或 | … | … | a | b | |
| 5 | 逻辑与 | … && … | a && b | |
| 4 | 逻辑或 | … || … | a || b | |
| 空值合并ES2020 | … ?? … | a ?? b | ||
| 3 | 三元运算符 | … ? … : … | 右到左 | a ? b : c |
| 2 | 赋值 | = | 右到左 | a = b |
| 1 | 逗号 | … , … | i=0, j=1 |
归纳
括号 > 对象函数调用 > 后置自增自减 > 一元 > 幂 > 二元 > 三元 > 赋值 > 逗号
其中 二元里的优先级:四则 > 移位 > 比较 > 位运算
自增自减
前置和后置,只有在使用了它们的返回值时才有区别,前置会返回新值,后置会返回旧值
++ 运算
let a = 1
a+ +a // a+(+a) = 1 + 1 = 2
a+++a // (a++)+a = 1 + 2 = 3
a+++a++ // (a++)+(a++) = 1 + 2 = 3逗号运算符
返回值是最后一个运算的值
短路效应
满足条件后不进行后续的运算
&&:返回第一个假值||:返回第一个真值??:返回第一个 非 null/undefined 的值?.:如果 ?. 左边为 null/undefined,就会立即停止运算并返回 undefined
如果所有的操作数都被计算过,则返回最后一个操作数
出于安全原因,JavaScript 禁止将 ?? 运算符与 && 和 || 运算符一起使用
可选链有三种形式:
obj?.prop、obj?.[prop]和obj.method?.()
switch
- switch 和 case 都允许任意表达式
- case 比较时是严格相等
- 如果没有 break,程序将不经过任何检查就会继续执行下一个 case
- 共享同一段代码的几个 case 分支可以被分为一组
注意
- 三目运算符只能与表达式结合
如:不能与 break/continue 结合使用:
(i > 0) ? continue : break // error! 错误语法连续赋值
赋值操作时,左侧变量已经固定,不会随着右侧变量变化而变化
如:
var a = { n: 1 }
var b = a
a.x = a = { n: 2 }
a.x // --> undefined
b.x // --> {n: 2}第三行赋值语句虽然改变了
a的指向,但是a.x中的这个a还是指向了赋值操作开始时就确定好的{n: 1}