ECMAScript 2022 (ES13) 发布也有段时间了,平时工作中也会用到一些,总结了一下新特性😎,大致如下:
- at()
- Top-level await
- Object.hasOwn()
- findLast和findLastIndex
- RegExp匹配索引
- Error的 cause 属性
- Class类 声明
- Class类 私有方法和私有属性
- Class类 静态字段和方法
- Class类 静态初始化块
- Class类 私有字段检查
1. at()
这是平时工作中用到多的方法,当给出负整数索引时,就会从数组的最后一项开始检索。以前我们引用数组最后一个元素一般用的是arr[arr.length - 1], 现在我们可以用arr.at(-1)来代替了。
🚀 ES2022之前
const arr = [1, 2, 3, 4]
console.log(arr[arr.length - 1]) // 4
🚀 ES2022之后
const arr = [1, 2, 3, 4]
console.log(arr.at(-1)) // 4
// 字符串和TypedArray(类型数组)也可以使用at(), 举个🌰
const str = "zhangSan"
console.log(str.at(-3)) // S
const typedArray = new Int8Array([1, 2, 3, 4, 5, 6])
console.log(typedArray.at(-2)) // 5
2. Top-level await
在ES2022之前,我们只能在async函数内部使用 await。但是现在,await 提升到模块中,不需要和 async 强绑定了。
🚀 ES2022之前
await Promise.resolve(console.log('zhangsan'))
// 输出 Uncaught SyntaxError: await is only valid in async function
// 解决方法
(async function() {
await Promise.resolve(console.log('zhangsan'))
// 输出 zhangsan
}());
🚀 ES2022之后
await Promise.resolve(console.log('zhangsan'))
// 输出: zhangsan
3. Object.hasOwn()
可以理解为是对hasOwnProperty的简化,看下面例子:
🚀 ES2022之前
for (let k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, 'key')) {
// ...
}
}
🚀 ES2022之后
for (let k in obj) {
if (Object.hasOwn(obj, 'key')) {
// ...
}
}
4. findLast和findLastIndex
在ES2022之前我们通过find和findIndex查找数组元素和下标,它是从第一个开始查找,查找到元素后返回。findLast和findLastIndex是从最后一个开始查找,查找到之后返回。
🚀 ES2022之前
// 查找数组第一个出现的奇数
const arr = [16, 11, 22, 18, 7, 15, 12, 13]
console.log(arr.find(t => t % 2 === 1)) // 11
console.log(arr.findIndex(t => t % 2 === 1)) // 1
🚀 ES2022之后
// 查找数组最后一个出现的奇数
const arr = [16, 11, 22, 18, 7, 15, 12, 13];
console.log(arr.findLast(t => t % 2 === 1)) // 13
console.log(arr.findLastIndex(t => t % 2 === 1)) // 7
5. RegExp匹配索引
ES2022新增了d修饰符,这个修饰符可以让exec()、match()的返回结果添加indices属性,该属性包含匹配的开始位置和结束位置
🚀 ES2022之前
const t = 'abcdefghijk'
const n = /def/
const r = n.exec(t)
console.log(r[0]) // def
console.log(r.index) // 3
🚀 ES2022之后
const t = 'abcdefghijk'
const n = /def/d
const r = n.exec(t)
console.log(r[0]) // def
console.log(r.index) // 3
console.log(r.indices[0]) // [3, 6]
6. Error的 cause 属性
🚀 ES2022之前
这是由阿里程序员提出的提案。ES2022为 Error 对象添加了一个cause属性,可以在生成错误时,添加报错原因的描述
async function getPerson(url) {
try {
const [res] = await fetch(url)
} catch(e) {
throw new Error(e)
}
}
getPerson('test');
// Uncaught Error: TypeError: (intermediate value) is not iterable
🚀 ES2022之后
async function getPerson(url) {
try {
const [res] = await fetch(url)
} catch(e) {
throw new Error('error', { cause: e })
}
}
try {
await getPerson('test')
} catch(e) {
console.error(e)
console.error(e.cause)
// Error: error
// TypeError: (intermediate value) is not iterable
}
7. Class类 声明
在ES2022之前,类字段只能在其构造函数中声明。但是现在可以在类的最外层范围内声明或定义它们
🚀 ES2022之前
class Person {
constructor() {
this.name = 'zhangsan'
this.age = 10
}
}
const person = new Person()
console.log(person.name) // zhangsan
🚀 ES2022之后
class Person {
name = 'zhangsan'
age = 10;
}
const person = new Person()
console.log(person.name) // zhangsan
8. Class类 私有方法和私有属性
以前我们声明私有方法或字段时,一般是在方法名开头加下划线_,但这并不能保持完全私有,所以ES2022添加了新属性#来定义私有方法和私有属性。我们只需要将#添加在方法名称的开头,这样将被声明为私有。
🚀 ES2022之前
class Person {
_name = 'zhangsan'
_getName() {
console.log(this._name)
}
}
const person = new Person()
console.log(person._name) // zhangsan
console.log(person._getName()) // zhangsan
🚀 ES2022之后
class Person {
#name = 'zhangsan'
#getName() {
console.log(this._name)
}
}
const person = new Person()
console.log(person.#name);
// 输出 Uncaught SyntaxError: Private field '#name' must be declared in an enclosing class
console.log(person.#getName())
// 输出 Uncaught SyntaxError: Private field '#getName' must be declared in an enclosing class
9. Class类 静态字段和方法
我们可以往类添加静态字段和方法,并且直接访问
🚀 ES2022之前
// 老写法
class Person {
name = 'zhangsan'
}
console.log(Person.name) // undefined
🚀 ES2022之后
class Person {
static name = 'zhangsan'
static getPerson() {
return this.name
}
}
console.log(Person.name) // zhangsan
console.log(Person.getPerson()) // zhangsan
10. Class类 静态初始化块
允许在类的内部设置一个代码块,在类生成时运行一次,很像静态的 constructor,主要是对静态属性进行初始化,并且可以将私有属性暴露出去。
let getPersonName
class Person {
static #name
static #age
static getPersonInfo() {
return `${this.#name}:${this.#age}`
}
static {
this.#name = 'zhangsan'
this.#age = 18
getPersonName = () => {
return this.#name
}
}
}
console.log(Person.getPersonInfo()) // zhangsan:18
// 访问私有变量
console.log(getPersonName()) // zhangsan
11. Class类 私有字段检查
这个特性可以用来判断某个对象是否为类的实例,还能用来判断对象或实例是否存在私有字段或方法
class Person {
#name
hasName() {
return #name in this
}
static isPerson(obj) {
return #name in obj
}
}
const person = new Person()
console.log(person.hasName()) // true
console.log(Person.isPerson(person)) // true
console.log(Person.isPerson({})) // false