乐趣区

关于javascript:几个关于运算符优先级的陷阱

前言

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 运算符优先级

结语

我倡议大多数时候在不同的运算符联合应用时增加圆括号
如果一眼不能看出优先级高下,最好增加圆括号确定优先级

退出移动版