上图:优先级越大数字越大,图片来源 MDN。
关于 JS 中的大多数运算,我想我们都不够陌生,而且看到了就能知道运算顺序。比如(优先级由高到低):一元大于二元大于三元,先乘除后加减,有括号先算括号里面的。
今天聚焦的逻辑运算符和三元运算符的优先级。
一般情况下,很少有人让逻辑运算符的且(&&)和或(||)一起出现,但是它们一旦一起出现,我想大多数人在不查询文档情况下,肯定以为他们是同一优先级,所以依次从左往右执行。但很不幸 && 比 || 的执行优先级高一级,类比下四则运算:&& 就像乘除,|| 就像加减。
比如如下代码:
const foo = a || b || c && d;
真正的元素规则为:
const foo = a || b || (c && d);
并不是从左往右,所以两者同时出现一定要加括号,指定运算优先级。
逻辑运算符如果结合三元运算符也是一大困惑,比如如下代码。
const n = a || b ? 1 : 2;
我们往往会把三元当做一个整体看,认为它的运算逻辑为:
const n = a || (b ? 1 : 2);
但实际上三元的运算优先级比逻辑低一级,所以真正的优先级为:
const n = (a || b) ? 1 : 2;
同理当逻辑运算符与三元运算符一起出现,一定要加括号指定运算优先级。
当然,我们是人,很容易忘记一些事情比如不加括号,所以加括号这件事情就交给程序去办吧,利用 ESLint 的 no-mixed-operators 规则可以轻松办到:
{
"no-mixed-operators": [
"error",
{
"groups": [
["+", "-", "*", "/", "%", "**"],
["&", "|", "^", "~", "<<", ">>", ">>>"],
["==", "!=", "===", "!==", ">", ">=", "<", "<="],
["&&", "||", "?:"],
["in", "instanceof"]
],
"allowSamePrecedence": true
}
]
}
no-mixed-operators 关于逻辑运算符的默认值为 ["&&", "||"],在这里面加个三元符号就行了 ["&&", "||", "?:"]。
可以使用 ESLint 的 playground 测试:
点击查看结果 逻辑运算符与三元运算符的优先级。
文档灵感来源:fix: always use github link