前言
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)
对于这种情况,必须加上圆括号以确保优先级
对于 ?? 运算符,我们可以看作和 || 是相同类型,都是在左侧不符合条件的时候使用右侧
实际上这三者的优先级是 && 高于 || 和 ??, || 和 ?? 是相同的优先级
参考
结语
我建议大多数时候在不同的运算符结合使用时添加圆括号
如果一眼不能看出优先级高低,最好添加圆括号确定优先级
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。