运算符 示例 说明
逻辑与 (&&) expr1 && expr2 如果expr1 能转换成false则返回expr1,否则返回expr2. 因此, 在Boolean环境中使用时, 两个操作结果都为true时返回true,否则返回false.
逻辑或(||) expr1 || expr2 如果expr1能转换成true则返回expr1,否则返回expr2. 因此,在boolean环境(在if的条件判断中)中使用时, 二者操作结果中只要有一个为true,返回true;二者操作结果都为false时返回false.
逻辑非(!) expr2 如果单个表达式能转换为true的话返回false,否则返回true.

能够转换为false的表达式有【 false、””(空字符串)、0、NaN、null、undefined 】
能够转化为true的值为【 true、任何非空字符串、任何非零数字值(包括无穷大)、任何对象 】

  1. a4=false && (3 == 4) // f && f 结果为 false
  2. a5="Cat" && "Dog" // t && t 结果为 Dog
  3. a6=false && "Cat" // f && t 结果为 false
  4. a7="Cat" && false // t && f 结果为 false a8 = true && 4 && "aaa"; //结果为"aaa"
  5. o4=false || (3 == 4) // f || f 结果为 false
  6. o5="Cat" || "Dog" // t || t 结果为 Cat
  7. o6=false || "Cat" // f || t 结果为 Cat(这个例子非常迷惑人) 这个可以在很多时候使用用于判断
  8. o7="Cat" || false // t || f 结果为 Cat

由于逻辑表达式的运算的顺序是从左到右,也可以用以下规则进行”短路”计算: 短路设计就会可以得到非空的后半段;

  • false && (anything) 短路计算的结果为false.
  • true || (anything) 短路计算的结果为 true

1. 数值分割符 _

ES2021 引入了数值分割符 _,在数值组之间提供分隔,使一个长数值读起来更容易。Chrome 已经提供了对数值分割符的支持,可以在浏览器里试起来。

  1. let number = 100_0000_0000_0000 // 0太多了不用数值分割符眼睛看花了
  2. console.log(number) // 输出 100000000000000

此外,十进制的小数部分也可以使用数值分割符,二进制、十六进制里也可以使用数值分割符。

  1. 0x11_1 === 0x111 // true 十六进制
  2. 0.11_1 === 0.111 // true 十进制的小数
  3. 0b11_1 === 0b111 // true 二进制

2. 零合并操作符 ??

零合并操作符 ?? 是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回右侧操作数,否则返回左侧操作数。

  1. expr1 ?? expr2

空值合并操作符一般用来为常量提供默认值,保证常量不为 null 或者 undefined,以前一般使用 || 来做这件事 variable = variable || ‘bar’。然而,由于 || 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0, ‘’, NaN, null, undefined)都不会被返回。这导致如果你使用 0、’’、NaN 作为有效值,就会出现不可预料的后果。
【 true || (anything) 短路计算的结果为 true 】

正因为 || 存在这样的问题,而 ?? 的出现就是解决了这些问题,?? 只会在左侧为 undefined、null 时才返回后者,?? 可以理解为是 || 的完善解决方案。

可以在浏览器中执行下面的代码感受一下:

  1. undefined || 'default' // 'default'
  2. null || 'default' // 'default'
  3. false || 'default' // 'default'
  4. 0 || 'default' // 'default'
  5. undefined ?? 'default' // 'default'
  6. null ?? 'default' // 'default'
  7. false ?? 'default' // 'false'
  8. 0 ?? 'default' // 0

我们常用的

  1. extraData?.user_name ?? "未登录"
  2. let a = {b: null, c: 10}
  3. a.c ??= 20
  4. console.log(a) // 输出 { b: 20, c: 10 }

3. 可选链操作符 ?.

可选链操作符 ?. 允许读取位于连接对象链深处的属性的值,而不必验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为 null 或者 undefined 的情况下不会引起错误,该表达式短路返回值是 undefined。

当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。

  1. const obj = {
  2. a: 'foo',
  3. b: {
  4. c: 'bar'
  5. }
  6. }
  7. console.log(obj.b?.c) // 输出 bar
  8. console.log(obj.d?.c) // 输出 undefined
  9. console.log(obj.func?.()) // 不报错,输出 undefined

以前可能会通过 obj && obj.a && obj.a.b 来获取一个深度嵌套的子属性,现在可以直接 obj?.a?.b 即可。

可选链除了可以用在获取对象的属性,还可以用在数组的索引 arr?.[index],也可以用在函数的判断 func?.(args),当尝试调用一个可能不存在的方法时也可以使用可选链。

调用一个对象上可能不存在的方法时(版本原因或者当前用户的设备不支持该功能的场景下),使用可选链可以使得表达式在函数不存在时返回 undefined 而不是直接抛异常。

4. 私有方法/属性

在一个类里面可以给属性前面增加 # 私有标记的方式来标记为私有,除了属性可以被标记为私有外,getter/setter 也可以标记为私有,方法也可以标为私有。

  1. class Person {
  2. getDesc(){
  3. return this.#name +' '+ this.#getAge()
  4. }
  5. #getAge(){ return this.#age } // 私有方法
  6. get #name(){ return 'foo' } // 私有访问器
  7. #age = 23 // 私有属性
  8. }
  9. const a = new Person()
  10. console.log(a.age) // undefined 直接访问不到
  11. console.log(a.getDesc()) // foo 23

5. 位运算符 >> 与 >>>

有符号右移操作符 >> 将第一个操作数向右移动指定的位数,多余的位移到右边被丢弃,高位补其符号位,正数补 0,负数则补 1。因为新的最左位与前一个最左位的值相同,所以符号位(最左位)不会改变。

  1. (0b111>>1).toString(2) // "11"
  2. (-0b111>>1).toString(2) // "-100" 感觉跟直觉不一样

6. 其他常用操作符

  1. 三元表达式:很简单了,大家经常用,expr ? expr1 : expr2 如果 expr 为真值则返回 expr1,否则返回 expr2
  2. 赋值运算符简写:加法赋值 +=、减法赋值 -=、乘法赋值 =、除法赋值 /=、求幂赋值 *=、按位或复制 |=、按位与赋值 &=、有符号按位右移赋值 >>=、无符号按位右移赋值 >>>=、逻辑空赋值 ??= ….
  3. 求幂运算符:var1 ** var2 相当于 Math.pow,结果为 var1 的 var2 次方

7.运算优先级

image.png