前言
JS 中的表达式十分弱小,对应的是与表达式相干的各种运算符,这些运算符可能任意组合,赋予 JS 极大的灵活性和弱小的组合性,很多时候用运算符就可代替许多用数行语句能力实现的性能,在这运算符弱小的背地,暗藏着优先级带来的隐患
大多 JS 开发者对于运算符的优先级并不十分相熟,这导致了如果肆意应用运算符,就可能因为优先级而导致诸多问题,甚至造成理论生产事变,所以,在拥抱运算符带来的弱小力量的同时,运算符带来的潜在的危险性也不容忽视
例子
一个例子
咱们可能之前有以下老代码
// Order 是一个构造函数,用于创立订单
function Order {// 一些代码}
// 如果 order 是 Order 的实例,做一些事,否则,做一些事
if(order instanceof Order) {// 一些代码}
业务变了,当初须要在 order 不是 Order 的实例的状况下做一些事
对于老手可能会这么写
if(order instanceof Order) {
}else {// 一些代码}
这运行起来是正确的,然而条件为 true 的块就空了,很不优雅
因而相熟运算符的人有可能会这么写
if(!order instanceof Order) {// 一些代码}
陷阱
对于这段代码的执行
参考上面的测试用例
let order = new Order();
// 咱们的代码
!order instanceof Order // false
// 咱们冀望的执行时的优先级
!(order instanceof Order) // false
目前,看起来是正确的
然而,如果是上面这个用例
let order = {};
// 咱们的代码
!order instanceof Order // false
// 咱们冀望的执行时的优先级
!(order instanceof Order) // true
这产生了不同的后果,尚未应用圆括号包裹不同的运算符,这可能导致问题,因为 ! 的优先级高于 instanceof
所以上述表达式实际上是这样运行的
(!order) instanceof Order;
这个表达式始终返回 false
而咱们冀望在 order 不为 Order 实例的时候返回 true,否则 false
所以,对于上述情况,必须要手动增加括号确保优先级
!(order instanceof Order);
上述情况是个常见的例子,咱们常常会应用 !xxx, !xx() !xx.xx[xx](),因而就可能呈现上述问题
两个其余的例子
运算符 ! typeof 和 ===
参考以下代码
// 表达式 1
typeof a === "string"
// 和 表达式 2
!typeof a === "string"
惯例用法,咱们晓得,typeof 的优先级大于 === 的优先级所以咱们晓得第一个表达式是这样执行的
(typeof a) === "string"
实际上 ! 的优先级和 typeof 的优先级雷同, 然而大于 === 的优先级
所以上述表达式 2 理论是这样的
(!(typeof a)) === "string"
而咱们冀望的执行是这样的
!((typeof a) === "string")
对于上述情况,倡议改用 !== 运算符,这样就不用在后面应用 !,也不用思考优先级问题,如果的确呈现了相似状况须要后面加 !,确保加上圆括号
逻辑运算符 && || ??
对于这三者,如果不相熟的话可能会认为优先级雷同,这可能会导致如下代码
a && b && c || d
因为 && 优先级高于 ||,所以上述代码理论执行的优先级是,
(a && b && c) || d
这有可能不合乎预期,有些时候咱们的预期是这样的
a && b && (c || d)
对于这种状况,必须加上圆括号以确保优先级
对于 ?? 运算符,咱们能够看作和 || 是雷同类型,都是在左侧不符合条件的时候应用右侧
实际上这三者的优先级是 && 高于 || 和 ??, || 和 ?? 是雷同的优先级
参考
mdn web docs 运算符优先级
结语
我倡议大多数时候在不同的运算符联合应用时增加圆括号
如果一眼不能看出优先级高下,最好增加圆括号确定优先级