ES2022精讲
ECMAScript的渊源
ECMAScript是一种语言规范:ECMAScript定义了一种脚本语言的标准,规定了语法、类型、语句、关键字等等。它由ECMA国际组织制定,旨在为各种脚本语言提供一个通用的标准。平时常说的ES6,全称就是ECMAScript2015,2015年发布的第六个版本规范。
JavaScript是一种编程语言:JavaScript是一种基于ECMAScript规范的编程语言,它实现了ECMAScript规范并添加了一些额外的功能,例如DOM操作、事件处理等。
TC39(Technical Committee 39)是负责制定ECMAScript规范的技术委员会。
https://github.com/tc39/ecma262

顶层设计 await(Top-level await)
作用:await可以脱离async函数,单独使用
1 | const message = await 'hello world'; |
注意
谨慎使用,当心阻塞后续操作
.at()
作用:可以获取索引对应的值,可支持 负数 。如下
1 | const arr = [1, 2, 3]; |
支持的类型
Array数组String字符串TypedArray类型化数组,如:Uint8Array等等
为什么 在之前的 [] 方法扩展,而是要用 at 方法?
[] 并非只有数组和字符串特有的方法。所有对象(引用类型的数据,如 Object 、Array 、 Function 等等 )都有。而且 [] 是本来就可以用 负数的,只不过是相当于负数是对象的key值,来获取Value值的意思。
1 | const arr = [1,2,3]; |
Object.hasOwn
作用:判断对象是否有指定的属性,用来取代 Object.prototype.hasOwnProperty 。
1 | let obj = { a: 1 }; |
**Object.prototype.hasOwnProperty 和 in 的区别**
in运算符可以检查继承的属性,而hasOwnProperty方法只检查对象自身的属性
1 | let obj ={a:1,b:2} |
现有的Object.prototype.hasOwnProperty的问题有哪些?
- 写法繁琐
1 | let obj = { a: 1 }; |
Object.create(null)使用 hasOwnProperty 会报错
Object.create(null) 创建的对象不会继承 Object.prototype ,将会丢失 hasOwnProperty 方法。用 Object.prototype.hasOwnProperty ****并不会出现这样情况。
1 | let obj = Object.create(null); |
为什么上诉例子使用 hasOwnProperty 要从原型上使用(Object.prototype.hasOwnProperty)而不是直接使用 ?
在上诉代码中,hasOwnProperty 可以直接使用,效果是一样的,如下:
1 | let obj = { a: 1 }; |
原因:
为了降低hasOwnProperty 被修改的可能性,防止不必要的bug。
由于 obj.hasOwnProperty 的 hasOwnProperty 本质上是obj的一个属性,不受到保护,可以被人为修改,可能会出现给对象定义属性名的时候为``hasOwnProperty` 。
1 | let obj = { a: 1, hasOwnProperty: 2 }; |
可以查看MDN详情
为什么不直接在Object.hasOwnProperty(object, property) 中直接修改使用?
答案
因为
Object本质上是个函数,Object()是空对象。并没有直接挂载hasOwnProperty属性 ,是通过原型链向上找到的。所以Object.hasOwnProperty等同于Object.prototype.hasOwnProperty1
2
3Object.prototype.hasOwnProperty = 123;
console.log(Object.prototype.hasOwnProperty); // 123
console.log(Object.hasOwnProperty); // 123
为什么不用 Map替换 Object?
Object操作上相对于Map方便一些- 请求发送数据需要 序列化数据
JSON格式,Map的话需要转成Object才行,而且有些数据(key值为引用类型)会丢失。key值1
2
3
4const map = new Map();
map.set({a:1},1);
map.set('b',2)
console.log(Object.fromEntries(map)) // {[object Object]: 1, b: 2}{a:1}变成了[object Object],进行了隐式类型转换(toString),因为Object的key值只能是string类型。1
2
3
4
5
6
7
8
9
10
11
12console.log(({a:1}).toString()); // '[object Object]'
let obj ={a:1,b:2}
obj[{c:3}] = 3
obj[3] = 3333
for (let key in obj){
console.log(key,typeof key)
}
// 3 string
// a string
// b string
// [object Object] string
Error Cause
作用:在 Error 类中添加了 cause 属性,用于传递错误信息。方便与错误的处理,对深层次的传递错误提供了良好的便利。
在以往的错误传递常用的有三种方式:
Error字符串拼接错误信息1
2
3
4
5
6
7
8
9
10
11
12
13
14async function queryHandlers() {
try {
JSON.parse('<')
} catch (err) {
throw new Error(`parse fail: ${err}`)
}
}
try {
await queryHandlers();
} catch (e) {
console.log(e);
// Error: parse fail: SyntaxError: Unexpected token '<', "<" is not valid JSON
}手动为
Error实例添加cause属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18async function queryHandlers() {
try {
JSON.parse('<')
} catch (err) {
const customError = new Error(`parse fail:`)
customError.cause = err;
throw customError
}
}
try {
await queryHandlers();
} catch (e) {
console.log(e);
// Error: parse fail:
console.log(e.cause);
// SyntaxError: Unexpected token '<', "<" is not valid JSON
}通过继承
Error类来实现自定义的error类型1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class CustomError extends Error {
constructor(msg, cause) {
super(msg);
this.cause = cause;
}
}
async function queryHandlers() {
try {
JSON.parse('<')
} catch (err) {
throw new CustomError('parse fail:', err);
}
}
try {
await queryHandlers();
} catch (e) {
console.log(e);
// Error: parse fail:
console.log(e.cause);
// SyntaxError: Unexpected token '<', "<" is not valid JSON
}
现在的 Error 中实例化的时候可以传入第二个参数,类型是对象,里面为 cause 属性赋值进行传递。
1 | async function queryHandlers() { |
Class Public Instance Fields
作用:之前要初始化公共的属性需要在 constructor 中进行初始化,现在可以在 constructor 之外去初始化公共属性。
1 | class Person { |
Private Instance Fields
作用:私有字段,可以使用 # 声明变量或方法为私有的,实例化之后无法直接访问的。
1 | class Person { |
Class Static Block
作用:提供了在未实例类中 关键字static 拥有计算的能力,不只是仅仅声明和赋值变量的能力。
先介绍一下Class 的 关键字 static : 只能在类型静态状态下访问,不可以实例化之后访问。可以定义变量或者方法。
使用场景: 工具函数 、 常量定义 等等。
1 | // 工具函数 |
之前如果需要对static进行计算需要再外部去修改,如:
1 | class Person { |
现在有了类静态代码块的功能,写法如下:
1 | class Person { |
RegExp Match Indices
作用:通过正则匹配字符串,输出匹配到的字符串的 开始索引位置和 结束索引位置。
处于性能的考虑,在已有的匹配模式上新增了 d 模式。之前的匹配模式有以下几种:
i忽略大小写g全局匹配m多行匹配
exec 新增 indices 属性,表示匹配到的字符串的 开始索引位置和 结束索引位置 。
1 | const reg = /(\d+)\.\d+/d; // 匹配数字加小数点加数字 |
输出的结果 12.3 代表匹配到的结果, 12 是正则中 (\d+) 捕获组的结果。