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.hasOwnProperty
1
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+)
捕获组的结果。