JavaScript ES2020必知必会新特性

前端下午茶

共 6081字,需浏览 13分钟

 · 2020-09-12

编者按:本文作者奇舞团前端工程师郭文涛。

探索应用新技术能提升社会效率和降低成本。

#1. Promise.allSettled

该方法接收一个可迭代的对象,例如Array,其中每个成员都是Promise。仅在所有这些Promise状态都改变为rejectedresolved时,返回的promise的处理程序作为输入传递一个数组,每个promise的结果包含status字符创,当statusfulfilled, 且返回一个value,反之,当statusrejected返回会包含一个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);


});

相关链接

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

https://tc39.es/proposal-promise-allSettled/

https://www.npmjs.com/package/promise.allsettled

#2. globalThis

ES2020 globalThis 提供了一个标准的方式来获取不同环境下的全局 this 对象(也就是全局对象自身),所以不用担心运行环境。

globalThis.location === window.location; // true

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis

#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

注意:  ?.不能用来赋值。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/可选链

#4. 空值合并运算符 Nullish Coalescing

空值合并运算符(??是一个逻辑运算符。当左侧操作数为 nullundefined 时,其返回右侧的操作数。否则返回左侧的操作数。

同理可以进行类似3 可选链操作符的短路操作。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator

#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。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import.meta

#6. BigInt

以前JavaScript中存储为整数的最大数量为pow(2, 53) - 1,ES2020 BigInt 是一种内置对象,它提供了一种方法来表示大于 253 - 1 的整数。BigInt 可以表示任意大的整数。

BitInt是在整数后面添加n的方式定义,或者用BitInt(*);

typeof 9007199254740991n === 'bigint'; // true


typeof BitInt('1') === 'bigint' // true;

注意:

  • 使用 Object 包装后, BigInt 被认为是一个普通 "object" :

typeof Object(1n) === 'object'; // true

  • 当使用 BigInt 时,带小数的运算会被取整。

5n / 2n; // 2n

  • BigIntNumber 不是严格相等的,但是宽松相等的。

1n === 1; // false;


1n == 1; // true;

  • BigIntNumber 混在一个数组中可以正常排序。

  • Object 包装的 BigInts 使用 object 的比较规则进行比较,只用同一个对象在比较时才会相等。

0n === Object(0n); // false


Object(0n) === Object(0n); // false


const o = Object(0n);


=== o // true

  • BigInt 在需要转换成 Boolean 的时表现跟 Number 类似。

  • 由于在 NumberBigInt 之间进行转换会损失精度,因而建议仅在值可能大于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"'

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt

#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();


}

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import

#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

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Class_elements

#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' ]

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll

#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新特性。

参考文章

https://v8.dev/features/tags/es2020

https://developer.mozilla.org/zh-CN


最后



如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:

  1. 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)

  2. 欢迎加我微信「qianyu443033099」拉你进技术群,长期交流学习...

  3. 关注公众号「前端下午茶」,持续为你推送精选好文,也可以加我为好友,随时聊骚。

点个在看支持我吧,转发就更好了


浏览 12
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报