说在前面:ES2020(即 ES11)于(2020 年 6 月)已经正式发布,在此之前进入 Stage 4 的 几项提案均已纳入规范,成为JavaScript 语言的新特性
ES2020
ESmodule迎来了一些增强
-
import() : 一种可以用
动态模块标识异步引入模块
的语法ES module 是一套静态的模块系统
静态加载:import/export 声明只能出现在顶层作用域,不支持按需加载和懒加载
静态标识:模块标识只能是字符串字面量,不支持运行时动态计算而来的模块名- 语法
import(moduleName)
- 描述:
- import()返回一个
promise
- 支持
async...await import()
import('./test.js').then((module) => { // do something }) let module = await import('./test.js')
- import()返回一个
- 实例
// page.js const add = function(a, b) { return a+b; } export { add } // index.html // 动态引入 async function sum(a, b) { await import('./page.js').then(res => { console.log(res.add(a,b)) }) // let res = await import('./page.js') // console.log(res.add(a,b)) } sum(4,4) // 8
- 与import相比
- 能够在函数、分支等
非顶层作用域
使用,按需加载
、懒加载
都不是问题 - 模块标识
不局限与字符串
,可以动态计算
模块标识 - 不仅限于
module
,在普通的script中也能使用
- 能够在函数、分支等
- 使用场景
- 当静态导入的模块
很明显的降低了
代码的加载速度且被使用的可能性很低
,或者并不需要马上使用它
。 - 当静态导入的模块
很明显的占用了大量系统内存
且被使用的可能性很低
。 - 当被导入的模块,在
加载时并不存在
,需要异步获取
- 当导入模块的说明符,需要
动态构建
。(静态导入只能使用静态说明符) - 当被导入的模块有
副作用
(这里说的副作用,可以理解为模块中会直接运行的代码),这些副作用只有在触发了某些条件才被需要
时。(原则上来说,模块不能有副作用,但是很多时候,你无法控制你所依赖的模块的内容)
不要滥用动态引入,只在
必要
的情况下引用。严格的静态模块机制
让基于源码的静态分析
、编译优化
有更大的发挥空间 - 当静态导入的模块
- 参考:
- 语法
-
import.meta : 一个对象,用来携带模块相关的元信息
- 定义:
- 是一个给JavaScript模块暴露
特定上下文
的元数据属性
的对象。它包含了这个模块的信息
,比如说这个模块的URL。
- 是一个给JavaScript模块暴露
- 语法
import.meta
- 描述
-
import.meta对象
由一个关键字"import"
,一个点符号
和一个meta属性名
组成。通常情况下"import."是作为一个属性访问的上下文,但是在这里"import"不是一个真正的对象。 -
import.meta对象
是由ECMAScript实现的,它带有一个null
的原型对象。这个对象可以扩展,并且它的属性都是可写
,可配置
和可枚举
的。
-
- 实例:
// index.mjs console.log(new URL(import.meta.url).searchParams.get('aaa')); // 5 console.log(1111, import.meta)
// index.html <script type="module"> import './index.mjs?aaa=5'; console.log(3333, import.meta)
结果依次为:
5 1111 {url: "http://127.0.0.1:5500/index.mjs?aaa=5"} 3333 {url: "http://127.0.0.1:5500/index.html"}
- 参考:
- 定义:
-
export * as ns from “mod” : 聚合导出语法
- 定义: 模块名称空间导出
Module namespace exports
- 语法
export * as ns from ‘mod' // 等同于 import * as ns from "mod"; export {ns};
- 描述:
- 这是对 ES 规范的有力补充,它允许开发者以
新名称
导出另一模块的命名空间外部对象
。同属于export … from …
形式的聚合导出。
- 这是对 ES 规范的有力补充,它允许开发者以
- 参考:
- export
这是对 ES 规范的有力补充,它允许开发者以新名称
导出另一模块的命名空间外部对象
。
同属于export … from …
形式的聚合导出
- export
- 定义: 模块名称空间导出
正式支持了安全的链式操作
Optional chaining可选链
:新运算符?.能够在属性访问、方法调用前检查其是否存在-
定义:
- 允许读取位于
连接对象链深处的属性的值
,而不必明确验证
链中的每个引用是否有效。
- 允许读取位于
-
描述:
- ?. 操作符的功能类似于
. 链式操作符
,不同之处在于,在引用为空(nullish )
(null 或者 undefined) 的情况下不会
引起错误,该表达式短路返回值是undefined
。 - 与函数调用一起使用时,如果给定的
函数不存在
,则返回 undefined。 - 当尝试访问
可能不存在
的对象属性时,可选链操作符将会使表达式更短
、更简明
。
- ?. 操作符的功能类似于
-
语法
// 调用属性 obj?.prop // 等价于 (obj !== undefined && obj !== null) ? obj.prop : undefined // 调用动态属性 obj?.[prop] // 等价于 (obj !== undefined && obj !== null) ? obj[prop] : undefined // 数组 arr?.[index] // 调用可选的函数或方法 fun?.(arg0, arg1) // 等价于 (fun !=== undefined && fun !== null) ? fun(arg0, arg1) : undefined
-
注意
- 当
调用的函数名
和属性名
相同时,调用会报错
- 当
-
参考:
-
Nullish coalescing Operator
:用来提供默认值的新运算符??空值合并运算符
- 定义:是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数
- 特点:类似于||,主要区别在于??只针对null和undefined,而||遇到任一假值都会返回右侧的默认值
- 使用
- 使用空值运算符代替三元计算符,更精确
- 为变量赋默认值,代替||运算符,可以避免假值影响结果
- 注意:
- 空值合并运算符??不能和 && || 同时使用,否则报错(运算符优先级暂未定义,可显示定义)
- 语法
activeValue ?? defaultValue // 等价于 activeValue !== null && activeValue !== undefined ? activeValue : defaultValue
js中遇到空字符串、0等,在进行逻辑判断的时候会默认为false。
??操作符严格让值等于null和undefined时才为false- 参考
提供大数运算的原生支持BigInt
-
定义:
- BigInt 是一种
内置对象
,它提供了一种方法来表示大于 2^53 - 1
的整数。这原本是 Javascript中可以用Number
表示的最大数字。BigInt 可以表示任意大的整数
。
- BigInt 是一种
-
定义方式:
- 可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt()。
-
对比Number:它在某些方面类似于 Number ,但是也有几个关键的不同点.
- 不能用于
Math
对象中的方法; - 不能和任何
Number 实例
混合运算,两者必须转换
成同一种类型。 - 在两种类型
来回转换时
要小心,因为 BigInt 变量在转换成 Number 变量时可能会丢失精度
- BigInt 和Number
不是严格相等
,但是是宽松相等
的 Number
和BigInt
可以进行比较。
- 不能用于
-
类型信息:
- typeOf类型检测时,BigInt 对象返回 “bigint” :
console.log(typeof 1n === 'bigint'); // true console.log(typeof BigInt('1') === 'bigint'); // true
- 使用 Object 包装后, BigInt 被认为是一个普通 “object” :
console.log(typeof Object(1n) === 'object') // true
- typeOf类型检测时,BigInt 对象返回 “bigint” :
-
BigInt 和Number不是严格相等,但是是宽松相等的
console.log(0n === 0) // ↪ false console.log(0n == 0) // ↪ true
-
Number 和 BigInt 可以进行比较
1n < 2 // ↪ true 2n > 1 // ↪ true 2n > 2 // ↪ false 2n >= 2 // ↪ true const mixed=[4n,6,-12n,10,4,0,0n]; // ↪ [4n, 6, -12n, 10, 4, 0, 0n] mixed.sort(); // ↪ [-12n, 0, 0n, 10, 4n, 4, 6]
-
实例方法
BigInt.prototype.toLocaleString()
- 返回此数字的 language-sensitive 形式的
字符串
。覆盖 Object.prototype.toLocaleString() 方法。
- 返回此数字的 language-sensitive 形式的
BigInt.prototype.toString()
- 返回以
指定基数(base)
表示指定数字的字符串。覆盖 Object.prototype.toString() 方法。
- 返回以
BigInt.prototype.valueOf()
- 返回指定对象的
基元值
。 覆盖 Object.prototype.valueOf() 方法。
- 返回指定对象的
-
参考
基础API新变化
- Promise.allSettled
- 定义:
promise.allSettled()
方法返回一个在所有给定的promise都已经fulfilled
或rejected
后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
- 使用情况:
- 当我们有
多个彼此不依赖
的异步任务成功完成时,或者说总是想知道每个promise的结果
时,通常使用它。
- 当我们有
- 语法:
/** * @parma iterable 一个可迭代的对象,例如Array,其中每个成员都是Promise * @return Promise 返回一个promise,该promise处理器输入一个对象数组。成员对象都包含一个status,当参数status是rejected,则存在一个reason(失败原因)。当status是fulfilled,则对象上存在一个value(成功结果)。 */ promise.allSettled(iterable);
- 实例:
const promise1 = Promise.resolve(3); const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo')); const promises = [promise1, promise2]; Promise.allSettled(promises). then((results) => results.forEach((result) => console.log(result)));
- 对比promise.all
- promise.all() 彼此
相互依赖
。 promise.allSettled()不依赖彼此
- promise.all() 有
一个失败即返回失败
,失败原因为第一个
失败promise的原因。 - promise.all() 成功时返回一个promise,该promise处理器输入为一个
数组
,数组内容为每个原始promise成功的value
- promise.all() 彼此
- 参考:
Promise.allSettled
- 定义:
- globalThis
- 定义
- 全局属性globalThis包含
全局的this值
,类似于全局对象(global object)。
- 全局属性globalThis包含
- 属性特性
writable true
可写enumerable false
不可枚举configurable true
可配置
- 获取全局对象
web
: window、self、framesweb workers
: selfNode.js
: global
- 描述
- globalThis 提供了一个
标准的方式
来获取不同环境
下的全局 this
对象(也就是全局对象自身)。不像 window 或者 self 这些属性,它确保可以在有无窗口的各种环境下
正常工作。所以,你可以安心的使用 globalThis,不必担心它的运行环境。为便于记忆,你只需要记住,全局作用域中的 this 就是 globalThis
。
- globalThis 提供了一个
- 参考:
- 定义
- String.prototype.matchAll
- 定义:
- matchAll()方法返回一个包含
所有匹配正则表达式的结果
及分组捕获
的迭代器
。
- matchAll()方法返回一个包含
- 语法:
/** * @parma regexp正则表达式对象,若传的不是正则表达式对象,则会隐式的调用new RegExp(obj)将其转换成RegExp. * RegExp必须是设置了全局模式g的形式,否则会抛出异常TypeError * @return 返回一个迭代器,包含所有匹配结果及分组捕获组(不可重用,结果耗尽需要再次调用方法,获取一个新的迭代器) */ str.matchAll(regexp)
- 实例:
const regexp = /t(e)(st(\d?))/g; const str = 'test1test2'; const res = str.matchAll(regexp); for(const mat of res) { console.log(mat) } // 结果耗尽,需再次调用方法,否则拿不到值 console.log(res.next()) // {value: undefined, done: true} console.log(res.next()) // {value: undefined, done: true} const array = [...str.matchAll(regexp)]; console.log(array[0]); // expected output: Array ["test1", "e", "st1", "1"] console.log(array[1]); // expected output: Array ["test2", "e", "st2", "2"]
- 对比match
- match()方法返回结果为
匹配的所有结果项数组
。 - match() 方法
可以没有g选项
,但是结果返回的是第一项匹配项
及该匹配项的捕获项列表
数组。 - matchAll() 方法返回结果为
迭代器
,而且没有g选项会报错
。
- match()方法返回结果为
- 参考
- 定义: