探索应用新技术能提升效率和降低成本。
1. Promise.allSettled
该方法接收一个可迭代的对象,例如Array
,其中每个成员都是Promise
。仅在所有这些Promise
状态都改变为rejected
或resolved
时,返回的promise的处理程序作为输入传递一个数组,每个promise的结果包含status
字符创,当status
为fulfilled
, 且返回一个value
,反之,当status
为rejected
返回会包含一个reason
。
const sleep = (timeout) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("sleep finish!");
}, timeout);
});
};
Promise.allSettled([
sleep(2000),
Promise.reject(new Error("error")),
]).then((res) => {
console.log("res", res);
});
<img src="http://blog.toringo.cn/image-20200418222325629.png" alt="image-20200418222325629" style="zoom:50%;" />
相关链接
2. globalThis
ES2020 globalThis
提供了一个标准的方式来获取不同环境下的全局 this
对象(也就是全局对象自身),所以不用担心运行环境。
globalThis.location === window.location; // true
3. 可选链操作符 Optional Chaining
语法:?.
减少访问深层对象时判断属性存不存在的问题。
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
};
console.log(adventurer.dog?.name);
// 输出undefined; adventurer.dog?.name等价于adventurer.dog && adventurer.dog.name
console.log(adventurer.dog?.getName?.()); // undefined
// 短路计算
let potentiallyNullObj = null;
let x = 0;
let prop = potentiallyNullObj?.[x++];
console.log(x); // 作为0的x将不会被递增,依旧输出0
注意: ?.
不能用来赋值。
4. 空值合并运算符 Nullish Coalescing
空值合并运算符(??
)是一个逻辑运算符。当左侧操作数为 null
或 undefined
时,其返回右侧的操作数。否则返回左侧的操作数。
<img src="http://blog.toringo.cn/image-20200418230033414.png" style="zoom:50%;" />
同理可以进行类似3 可选链操作符的短路操作。
5. import.meta
import.meta
对象是由ECMAScript实现的,它带有一个null
的原型对象。这个对象可以扩展,并且它的属性都是可写,可配置和可枚举的。
<script type="module" src="index.js"></script>
// index.js
console.log(import.meta);
// 打印出{url: "http://127.0.0.1:8099/html/2020-JavaScript/index.js"}
React
中使用参考babel
插件babel-plugin-syntax-import-meta。
6. BigInt
以前JavaScript中存储为整数的最大数量为pow(2, 53) - 1
,ES2020 BigInt
是一种内置对象,它提供了一种方法来表示大于 253 - 1
的整数。BigInt
可以表示任意大的整数。
BitInt
是在整数后面添加n
的方式定义,或者用BitInt(*)
;
<img src="http://blog.toringo.cn/1587265198006.jpg" alt="1587265198006" style="zoom:50%;" />
typeof 9007199254740991n === 'bigint'; // true
typeof BitInt('1') === 'bigint' // true;
注意:
-
使用
Object
包装后,BigInt
被认为是一个普通 "object" :typeof Object(1n) === 'object'; // true
-
当使用
BigInt
时,带小数的运算会被取整。5n / 2n; // 2n
-
BigInt
和Number
不是严格相等的,但是宽松相等的。1n === 1; // false; 1n == 1; // true;
-
BigInt
和Number
混在一个数组中可以正常排序。 -
Object
包装的BigInt
s 使用 object 的比较规则进行比较,只用同一个对象在比较时才会相等。0n === Object(0n); // false Object(0n) === Object(0n); // false const o = Object(0n); o === o // true
-
BigInt
在需要转换成Boolean
的时表现跟Number
类似。 - 由于在
Number
与BigInt
之间进行转换会损失精度,因而建议仅在值可能大于253 时使用BigInt
类型,并且不在两种类型之间进行相互转换。 -
对任何
BigInt
值使用JSON.stringify()
都会引发TypeError
,因为默认情况下BigInt
值不会在JSON
中序列化。可以手动实现:JSON.stringify(BigInt('0')); // Uncaught TypeError: Do not know how to serialize a BigInt BigInt.prototype.toJSON = function() { return this.toString(); } JSON.stringify(BigInt('0')); // '"0"'
7. 动态导入 Dynamic Import
关键字import可以像调用函数一样来动态的导入模块, 这种方式会返回一个promise
。
if(flag) {
import('./module.js').then(fn => {
fn.say();
})
}
// 也可以用async/await
if(flag) {
const fn = await import('./module.js');
fn.say();
}
8. 私有类变量 Private Class Variables
私有实例字段 是通过# names句型(读作“哈希名称”)声明的,访问和声明时需要 带着#
。只能在内部使用。
class Cat {
#name = 'tom';
getName() {
console.log(this.#name);
}
}
const cat = new Cat();
cat.getName(); // tom
cat.#name; // Uncaught SyntaxError: Private field '#name' must be declared in an enclosing class
class Pig extends Cat {}
const pig = new Pig();
pig.getName(); // tom
pig.#name; // Uncaught SyntaxError: Private field '#name' must be declared in an enclosing class
私有实例方法, 语法类似都是#names
。
class ClassWithPrivateMethod {
#privateMethod = () => {
return "hello world";
};
getPrivateMessage() {
return this.#privateMethod();
}
}
const instance = new ClassWithPrivateMethod();
console.log(instance.getPrivateMessage()); // hello world
console.log(instance.#privateMethod()); // SyntaxError: Private field '#privateMethod' must be declared in an enclosing class
静态私有字段
class ClassWithPrivateStaticField {
static #PRIVATE_STATIC_FIELD;
static publicStaticMethod() {
ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42;
return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD;
}
}
console.log(
ClassWithPrivateStaticField.publicStaticMethod() ===
ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD
);
// SyntaxError: Private field '#PRIVATE_STATIC_FIELD' must be declared in an enclosing class
静态私有方法
class ClassWithPrivateStaticMethod {
static #privateStaticMethod = () => {
return 42;
};
static publicStaticMethod() {
return ClassWithPrivateStaticMethod.#privateStaticMethod();
}
}
console.log(ClassWithPrivateStaticField.publicStaticMethod() === 42); // true
9. String.prototype.matchAll
语法: str.matchAll(regexp)
给定一个字符串和一个正则表达式,matchAll()
方法返回所有与该字符串匹配正则表达式的结果的迭代器,包括捕获groups。
let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';
let array = [...str.matchAll(regexp)];
console.log(array[0]); // ["test1", "e", "st1", "1"]
console.log(array[1]); // ["test2", "e", "st2", "2"]
let array2 = str.match(regexp);
console.log(array2); // [ 'test1', 'test2' ]
10. For ... in 定义了明确的顺序
ECMA规范未指定for (x in y)
应按哪个顺序运行。即使以前浏览器自己实现了一致的顺序,但ES2020已正式对其进行标准化。
11. 模块名称空间导出 Module namespace exports
在JavaScript
中可以使用一下语法:
import * as utils from './module.js';
// 但是,不export存在对称语法, 但是现在已支持
export * as utils from './module.js';
// 等效于
import * as utils from './utils.mjs';
export { utils };
欢迎留言指正,或罗列更多的ES新特性。
参考文章
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。