JS 中强大的操作符

数值分割符 _

ES2021 引入了数值分割符 _,在数值组之间提供分隔,使一个长数值读起来更容易。

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

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

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

逗号运算符 ,

逗号操作符对它的每个操作数求值(从左到右),并返回最后一个操作数的值。

1
expr1, expr2, expr3...

示例:将数组的第一项和第二项调换,并返回两项之和:

1
2
3
4
5
function reverse(arr) {
return [arr[0], arr[1]]=[arr[1], arr[0]], arr[0] + arr[1]
}
const list = [1, 2]
reverse(list) // 返回 3,此时 list 为[2, 1]

零合并操作符 ??

零合并操作符 ?? 是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回右侧操作数,否则返回左侧操作数。空值合并操作符一般用来为常量提供默认值,保证常量不为 null 或者 undefined

1
2
3
4
5
6
7
8
9
ndefined || 'default' // 'default'
null || 'default' // 'default'
false || 'default' // 'default'
0 || 'default' // 'default'

undefined ?? 'default' // 'default'
null ?? 'default' // 'default'
false ?? 'default' // 'false'
0 ?? 'default' // 0

另外在赋值的时候,可以运用赋值运算符的简写 ??=

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

可选链操作符 ?.

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

1
2
3
4
5
6
7
8
9
10
const obj = {
a: 'foo',
b: {
c: 'bar'
}
}

console.log(obj.b?.c) // 输出 bar
console.log(obj.d?.c) // 输出 undefined
console.log(obj.func?.()) // 不报错,输出 undefined

私有方法/属性

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

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person {
getDesc(){
return this.#name +' '+ this.#getAge()
}

#getAge(){ return this.#age } // 私有方法

get #name(){ return 'foo' } // 私有访问器
#age = 23 // 私有属性
}
const a = new Person()
console.log(a.age) // undefined 直接访问不到
console.log(a.getDesc()) // foo 23

双位运算符 ~~

可以使用双位操作符来替代正数的 Math.floor( ),替代负数的 Math.ceil( )。双否定位操作符的优势在于它执行相同的操作运行速度更快。Math.floor(v)取小于等于v的值,向下取整,则Math.ceil相反

1
2
3
4
5
6
7
~~4.5                // 4
Math.floor(4.5) // 4
Math.ceil(4.5) // 5

~~-4.5 // -4
Math.floor(-4.5) // -5
Math.ceil(-4.5) // -4

void运算符

void运算符 对给定的表达式进行求值,然后返回undefined

可以用来给在使用立即调用的函数表达式(IIFE)时,可以利用 void 运算符让 JS 引擎把一个 function 关键字识别成函数表达式而不是函数声明。

1
2
3
4
function iife() { console.log('foo') }()       // 报错,因为JS引擎把IIFE识别为了函数声明
void function iife() { console.log('foo') }() // 正常调用
~function iife() { console.log('foo') }() // 也可以使用一个位操作符
(function iife() { console.log('foo') })() // 或者干脆用括号括起来表示为整体的表达式

还可以用在箭头函数中避免传值泄漏,箭头函数,允许在函数体不使用括号来直接返回值。这个特性给用户带来了很多便利,但有时候也带来了不必要的麻烦,如果右侧调用了一个原本没有返回值的函数,其返回值改变后,会导致非预期的副作用。

1
const func = () => void customMethod()   // 特别是给一个事件或者回调函数传一个函数时

安全起见,当不希望函数返回值是除了空值以外其他值,应该使用 void 来确保返回 undefined,这样,当 customMethod 返回值发生改变时,也不会影响箭头函数的行为。

其他常用操作符

  • 三元表达式:很简单了,大家经常用,expr ? expr1 : expr2 如果 expr 为真值则返回 expr1,否则返回 expr2

  • 赋值运算符简写:加法赋值 +=、减法赋值 -=、乘法赋值 *=、除法赋值 /=、求幂赋值 **=、按位或复制 |=、按位与赋值 &=、有符号按位右移赋值 >>=、无符号按位右移赋值 >>>=、逻辑空赋值 ??= ….

  • 求幂运算符var1 ** var2 相当于 Math.pow,结果为 var1var2 次方