目录
ES12(2021)特性
replaceAll()
Promise.any
WeakRef
WeakRef 的使用场景
逻辑运算符和赋值表达式 、数字分隔符
ES13(2022)新特性
class的扩展
await在顶层使用
Object.hasOwn()
Array.prototype.at()
d修饰符
ES12(2021)特性
replaceAll()
replaceAll() 方法用于将字符串中所有匹配的子字符串替换为指定的替换字符串。
【语法】str.replaceAll(searchValue, replaceValue)
【参数】searchValue:要被替换的子字符串或正则表达式。replaceValue:用于替换的字符串。
let str = "Hello, world! Hello, universe!";
let newStr = str.replaceAll("Hello", "Hi");
console.log(newStr); // 输出:Hi, world! Hi, universe!
Promise.any
Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise。
【语法】Promise.any(iterable)
【参数】iterable:一个可迭代对象(如数组),其中包含多个 Promise。
【返回值】
- 返回一个新的 Promise。
- 如果至少有一个 Promise 成功解决(fulfilled),则返回该 Promise 的解决值。
- 如果所有的 Promise 都被拒绝(rejected),则返回一个拒绝的 Promise,并带有一个 AggregateError,其中包含所有被拒绝的错误。
在这个例子中,promise2
是第一个成功解决的 Promise,所以 Promise.any()
返回 promise2
的解决值 “Success 2”。
const promise1 = Promise.reject('Error 1');
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'Success 2'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 200, 'Success 3'));Promise.any([promise1, promise2, promise3]).then((value) => {console.log(value); // "Success 2"
}).catch((error) => {console.log(error);
});
如果所有的 Promise 都被拒绝,Promise.any()
将返回一个包含所有拒绝原因的AggregateError。
const promise1 = Promise.reject('Error 1');
const promise2 = Promise.reject('Error 2');
const promise3 = Promise.reject('Error 3');Promise.any([promise1, promise2, promise3]).then((value) => {console.log(value);
}).catch((error) => {console.log(error); // AggregateError: All promises were rejected
});
使用场景简要说明
从最快的服务器检索资源、容错处理、超时与重试机制、并行任务处理
WeakRef
WeakRef是 ES12 引入的一个新特性,用于创建对对象的弱引用。弱引用不会阻止垃圾回收器回收对象,即使该对象仍然被弱引用持有。WeakRef通常与 FinalizationRegistry
结合使用,用于在对象被垃圾回收时执行清理操作。
【语法】const weakRef = new WeakRef(targetObject);
【其他】
deref()
:返回弱引用指向的目标对象。如果目标对象已被垃圾回收,则返回undefined
。
创建弱引用
const obj = { name: "liming" };
const weakRef = new WeakRef(obj);// 访问目标对象
const target = weakRef.deref();
console.log(target); // { name: "liming" }
检查对象是否被回收
let obj = { name: "Bob" };
const weakRef = new WeakRef(obj);// 解除对 obj 的强引用
obj = null;// 强制触发垃圾回收(仅用于演示,实际环境中不应手动调用)
global.gc();// 检查对象是否被回收
setTimeout(() => {const target = weakRef.deref();console.log(target); // undefined(对象已被回收)
}, 1000);
WeakRef
的使用场景
缓存系统
在缓存系统中,可以使用 WeakRef
来缓存对象。当内存不足时,垃圾回收器会自动回收这些对象,从而避免内存泄漏。
const cache = new Map();function getCachedData(key) {let cachedRef = cache.get(key);if (cachedRef) {const cachedData = cachedRef.deref();if (cachedData) {return cachedData;}}// 重新获取数据并缓存const newData = fetchData(key);cache.set(key, new WeakRef(newData));return newData;
}
避免内存泄漏
在需要持有对象引用但又不想阻止垃圾回收的场景中,WeakRef
是一个理想的选择。
class EventListener {constructor(target) {this.targetRef = new WeakRef(target);this.handleEvent = this.handleEvent.bind(this);target.addEventListener("click", this.handleEvent);}handleEvent(event) {const target = this.targetRef.deref();if (target) {console.log("Event triggered on:", target);} else {// 目标对象已被回收,清理事件监听器event.currentTarget.removeEventListener("click", this.handleEvent);}}
}
监听对象生命周期
结合 FinalizationRegistry
,可以在对象被垃圾回收时执行清理操作。
const registry = new FinalizationRegistry((heldValue) => {console.log(`Object with value ${heldValue} has been garbage collected.`);
});let obj = { name: "Charlie" };
const weakRef = new WeakRef(obj);// 注册清理回调
registry.register(obj, "some metadata");// 解除对 obj 的强引用
obj = null;// 当 obj 被垃圾回收时,会触发清理回调
逻辑运算符和赋值表达式 、数字分隔符
逻辑运算符和赋值表达式,新特性结合了逻辑运算符(&&,||,??)和赋值表达式而JavaScript已存在的 复合赋值运算符有:
- all= b //等价于 a=a(a= b)
- &&= b //等价于 a=a&&(a= b)
- ??= b //等价于 a=a??(a= b)
数字分隔符,可以在数字之间创建可视化分隔符,通过_下划线来分割数字,使数字更具可读性
const money =1 000 000 000;
//等价于
const money = 1000000000:1 000 000 000=== 1000000000; //true
ES13(2022)新特性
class的扩展
在ES2022中允许我们并不在constructor
中定义类的成员,示例代码如下:
class user {name = '李明'
}
、*两者是一致的 */
class user {constructor(){name = '李明'}
}
在ES2022中允许我们使用#
开头命名的变量作为类的私有成员
在ES2022(即ECMAScript 2022)中,引入了#
符号,允许开发者使用私有字段(私有成员变量)来封装类的内部状态,防止外部直接访问。这是通过在属性名前加上#
符号来实现的。这种方式增强了封装性,有助于维护代码的清晰和安全。
定义私有字段:在类的字段名前加上#
符号。
class MyClass {#myPrivateField = '这是一个私有字段';showPrivateField() {console.log(this.#myPrivateField);}
}const instance = new MyClass();
instance.showPrivateField(); // 输出: 这是一个私有字段
注:只能在类的内部通过this
关键字来访问私有字段。从类的外部或类的其他方法中直接访问会导致错误。
await在顶层使用
在ES2022中,JavaScript引入了顶层await的功能,允许在模块的顶层直接使用await关键字,而不需要将其包裹在async函数中。这种写法可以简化代码,使得异步操作更加直观和简洁。
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await res.json();
console.log(data);
这段代码会在模块的顶层直接执行await操作,等待fetch请求完成并获取数据,然后继续执行后续的代码 。
顶层await的特点和限制
- 阻塞模块加载:顶层await会阻塞模块的加载,直到所等待的Promise解决或拒绝。这意味着在使用顶层await的模块中,所有的导入操作都会被延迟,直到当前模块中所有的顶层await完成。
- 错误处理:使用顶层await时,如果Promise被拒绝,模块将无法加载。因此,通常用于那些必须等待某些操作完成才能继续执行的场景。
Object.hasOwn()
Object.hasOwn()是ES2022中新增的一个静态方法,用于检测某个属性是否属于一个对象,并且该属性是对象自身的属性,而不是继承自原型链的属性。该方法返回一个布尔值,如果对象具有指定的自身属性,则返回true,否则返回false。
【语法】Object.hasOwn(obj, propName)
【参数】obj:待检查的对象;propName:待检查的属性名(以字符串形式表示)。
const obj = {a: 1};
console.log(Object.hasOwn(obj, 'a')); // 输出:true
console.log(Object.hasOwn(obj, 'b')); // 输出:false
Array.prototype.at()
ES2022中新增的at()方法,它的作用是获取数组中的某个成员,它的参数是数组的索引,与直接使用索引的方式不同,它允许我们传递负值,等同于从后面倒数。
【语法】arr.at(index)
【参数】arr是一个数组,index是一个整数,表示要访问的元素的索引。如果
index
不在数组范围内,则返回undefined
【支持类型】String、Array、Typed Array
// 正数索引:从数组起始位置开始索引
let fruits = ['apple', 'banana', 'cherry'];
console.log(fruits.at(1)); // 'banana'// 负数索引:从数组末尾开始反向索引
let numbers = [1, 2, 3, 4, 5];
console.log(numbers.at(-1)); // 5
d修饰符
ES2021(也称为ES12)引入了多个新特性,其中就包括d修饰符。d修饰符用于匹配字符串中的文字模式,忽略字符串的大小写。
d修饰符的用途和效果
d修饰符的主要作用是匹配字符串中的文字模式时忽略大小写。例如,使用d修饰符可以匹配“Hello”和“hello”,因为它们在大小写上有所不同,但使用d修饰符后,它们都会被视为相同的文字模式。这个修饰符可以让exec()
、match()
的返回结果添加indices
属性,在该属性上面可以拿到匹配的开始位置和结束位置。
const text = 'zabbcdef';
const re = /ab/d;
const result = re.exec(text);result.index // 1
result.indices // [ [1, 3] ]
上一章:ES10(2019)、ES11(2020) 新增特性(八)