Skip to content

从new xx()和new xx的区别中,整理JS中操作符的优先级

绝弹

最近在工作中写日期格式化时,遇到一个问题,先来看下面的代码:

ts
// 写法一
new Date().toISOString;

// 写法二
new Date.toISOString();

运行结果如下:

猜测是优先级的问题,然后在 MDN 找到了答案,它们确实是两个不同的优先级,如下图:

以上,方式一中的 . 优先级最高,但其左边需要先求值,因而先执行new Date()得到实例,再返回实例上的toISOString属性;而方式二中的 . 优先级也是最高,但其左边不用求值,因而可以先执行Date.toISOString得到toISOString值(Date 上不存在该属性,因此该值为 undefined),再尝试进行new toISOString操作时报错发生。

优先级

我印象中的运算符只有四十几个,没想到在 MDN 里面找到的有六十几个。说实话,上面的运算符以前真没注意过,趁着空闲我决定将这些运算符整理下,整理后总体分为下面的五大类:

一级运算符

大部分是一元操作符。

运算符类型说明
( … )分组优先级最高的运算符
… . …成员访问静态访问
[]需计算的成员访问动态访问
new xx()new(带参数列表)实例化
()函数调用函数调用
?.可选链(Optional chaining)a?.b类似于a === null || a === void 0 ? void 0 : a.b;
new …new(无参数列表)实例化
… ++后置递增先返回再+1,例如 let a = 1; const b = a++; // b: 1 a: 2。比较常见的是在 for 循环中进行后置递增。
… --后置递减同上
! …逻辑非 (!)
~ …按位非 (~)
+ …一元加法 (+)可用于把字符串转换为数值,例如+'1'将得到1
- …一元减法 (-)同上
++ …前置递增与后置递增不同,先执行+1 再返回
-- …前置递减同上
typeof …typeof返回值只有这几个:string | number | boolean | undefined | null | function | object
void …void比较常见的是使用void 0代替 undefined,因为在以前 undefined 是可以作为变量名使用的。
delete …delete删除对象的属性
await …await等待某个 promise 执行成功

算符运算符

运算符类型说明
… ** …幂 (**)
… * …乘法 (*)
… / …除法 (/)
… % …取余 (%)
… + …加法 (+)
… - …减法 (-)
… << …按位左移 (<<)通常用于二进制数据的移位, 例如:(4)<<1 将得到8。过程:十进制4转换为二进制100, 左移一位得到1000,再转换为十进制即为8
… >> …按位右移 (>>)同上
… >>> …无符号右移 (>>>)同上
… < …小于 (<)对于数值,比较大小
… <= …小于等于 (<=)
… > …大于 (>)
… >= …大于等于 (>=)

比较运算符

运算符类型说明
… in …in判断某个属性是否存在于对象上,会顺着原型链进行查找,可以用Object.prototype.hasOwnProperty.call(obj, 'xx')进行检测自身的属性是否存在。
… instanceof …instanceof判断右边的对象,是否在左边对象的原型链上。
… == …相等 (==)左右两边的值可能会先做隐式转换,再进行比较,例如: '1' == 1 //true
… != …不相等 (!=)同上
… === …一致/严格相等 (===)左右两边的值不做隐式转换,直接比较,例如:'1' === 1 // false
… !== …不一致/严格不相等 (!==)同上

布尔运算符

| 运算符 | 类型 | 说明 | | :------------- | :------------------ | --------------------------------------------------------------------------------------------------------------------------- | --- | | … & … | 按位与 (&) | 常用于对二进制数值进行操作 | | … ^ … | 按位异或 (^) | | … | … | 按位或 (|) | | … && … | 逻辑与 (&&) | | … || … | 逻辑或 ( | | ) | | … ?? … | 空值合并 (??) | 当左边的值不为 undefined 或 null 时,返回左边,否则返回右边, 具体代码可能是这样的\n: a !== null && a !== void 0 ? a : b; |

赋值运算符

运算符类型说明
… ? … : …条件(三元)运算符可以在简单场景中代替 if/else 使用,不过自从出了??运算符,这个运算符用的比较少
… = …赋值
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
= …
… &&= …
= …
… ??= …
… , …逗号 / 序列优先级最低的运算符,由于其会返回最后一个值,在某些简短操作中也会用到,例如:const map = items.reduce((m, i) => (m[i.id]=i,m), {})

结语

优先级的重要性不言而喻,往后还是要多多温习。