ES6+新特性扫盲

September 11, 2021

ES2021

逻辑赋值运算符

类似于 += *= 等运算符:

  • ??=
  • &&=
  • ||=
let a = null
a ??= "flag" // a = a ?? "flag"
a &&= "flag" // a = a && "flag"
a ||= "falg" // a = a || "flag"

数字分隔符

允许在数字中间添加下划线 _ 增强可读性.

不允许出现在数字的首尾位置.

如: 1_000_000

注意: 带下划线的 String 类型的数字无法正常转换:

Number(1_000) // 1000
Number("1_000") // NaN

Promise.any()

接收一个 Promise 数组, 返回第一个 fulfilled 的 Promise 返回值.

当所有的 Promise 都 rejected 时, 进入 catch 块并返回 AggregateError 类型的错误.

对比 Promise.race() 是返回第一个 fulfilledrejected 的 Promise 返回值.

String.replaceAll()

String.replace() 只替换第一次匹配的字符

WeakRefs 与 FinalizationRegistry

WeakRefs 为对象创建一个弱引用, 弱引用不会组织 JS 引擎垃圾回收期的回收, 一般很少使用.

使用 FinalizationRegistry 对象可以在垃圾回收器回收对象时, 执行回调函数:

// 构建监听对象被垃圾回收器清除的回调
const registry = new FinalizationRegistry(heldValue => {
  console.log("----", heldValue)
})

const obj = {}
const token = {}

// 注册监听
registry.register(obj, "obj deleted!", token)

// 取消监听
// registry.unregister(token);

// 可能很久以后,回调执行
// ---- obj deleted!

ES 2020

链式判断运算符 ?.

支持 obj?.a?.b?.c 运算, 当中间某个属性为 nullundefined 时, 直接返回 undefined .

同时支持 obj?.[expr] 方括号形式与 fun?.(...args) 函数调用形式.

?? 运算符

类似于 || , 但只有运算符左侧值为 nullundefined 时才返回右侧值.

const username = list?.info?.base?.username ?? 'user';

|| 运算符在左侧为 null undefined '' false0 时都会返回右侧值.

import() 函数

之前的 import 只能用在模块顶层, 无法支持动态加载或条件导入模块.

import() 函数支持动态加载模块, 返回一个 Promise :

if (page === "home") {
  import("./home.js")
    .then(({ export1, export2 }) => {
      // 加载成功
    })
    .catch(err => {
      // 加载失败
    })
}

适用于:

  • 按需加载(如点击某按钮)
  • 条件加载
  • 动态的模块路径

export * as xx from "someModule"

相当于以下两个语句:

  • import * as xx from "someModule";
  • export {xx};

BigInt 类型

可精确表示任意位数的整数, BigInt 类型的数据需要添加后缀 n .

const n = 34242345425325n
typeof n // "bigint"
// 作为构造函数
BigInt(3243) // 3243n
BigInt("324") // 324n
BigInt(false) // 0n
BigInt(true) // 1n

Promise.allSettled()

接收一组 Promise 实例作为参数, 当这些 Promise 都返回结果, 无论是 fulfilled 还是 rejected , 状态都会变为 fulfilled , 返回 [{ status: "fulfilled" | "rejected", value?: any, reason?: any }]

const resolved = Promise.resolve(42)
const rejected = Promise.reject(-1)

const allSettledPromise = Promise.allSettled([resolved, rejected])

allSettledPromise.then(function (results) {
  console.log(results)
})
// [
//    { status: 'fulfilled', value: 42 },
//    { status: 'rejected', reason: -1 }
// ]

Promise.allSettled(), Promise.all(), Promise.race()

String.matchAll()

返回一个正则表达式在当前字符串中的所有匹配.

返回一个迭代器, 可以使用 for..of 遍历或使用 Array.from() 转为数组遍历.

let regex = /t(e)(st(\d?))/g
let string = "test1test2test3"
let r = string.matchAll(regex)
Array.from(r)
// [["test1", "e", "str1", "1"],
//  ["test2", "e", "str2", "2"],
//  ["test3", "e", "str3", "3"]]

globalThis

全局属性 globalThis 包含全局的 this 对象.

以前在不同环境下获取全局 this 对象的方法各不相同, 如:

  • 在 Web 中通过 windowself 获取 this
  • 在 WebWorkers 中只能通过 self 获取 this
  • 在 Nodejs 中需要使用 global 获取 this

需要通过判断各种对象是否存在来获取 this, 较为繁琐.

globalThis 提供了一个标准方式来获取全局 this , 在各种环境下都适用.

for..in 定义了明确的顺序

for (x in y) 语句将以规定的顺序执行.

import.meta

返回带有 url 属性的对象, 可获取模块的基础 URL.

;<script type="module" src="module.js"></script>

console.log(import.meta) // { url: "file:///home/user/module.js" }

ES 2019

String.trimStart() / String.trimEnd()

单独去掉 String 头或尾部的空白字符.

Object.fromEntries()

Object.entries() 的逆过程, 将 [[key, value]] 形式的键值对转为对象结构:

let obj = { a: "aa", b: 40 }
let entries = Object.entries(obj)
entries // [["a", "aa"], ["b", 40]]
let obj1 = Object.fromEntries(entries)
obj1 // {a: "aa", b: 40}

Array.flat() / Array.flatMap()

  • Array.flat([depth = 1]) 按照指定深度展开/铺平数组, 默认深度为 1

    const arr1 = [1, 2, [3, 4]]
    arr1.flat() // [1,2,3,4]
    const arr2 = [1, 2, [[[3, 4]]]]
    arr2.flat(2) // [1,2,[3,4]]
    arr2.flat(3) // [1,2,3,4]
    
  • Array.flatMap() 即 Array.map() + Array.flat(1)

    let arr1 = ["it's Sunny in", "", "California"]
    
    arr1.map(x => x.split(" "))
    // [["it's","Sunny","in"],[""],["California"]]
    
    arr1.flatMap(x => x.split(" "))
    // ["it's","Sunny","in", "", "California"]
    

catch 参数可省略

支持语法 try {...} catch {...} .

Symbol.description

获取 Symbol 对象创建时的描述信息:

const symbol = Symbol("This is a symbol")
symbol // Symbol(This is a symbol)
symbol.description // "This is a symbol"

加强 JSON.parse() 与 JSON.stringify()

之前 JSON 字符串中包含行分隔符 \u2028 或 段落分隔符 \u2029 时, 调用 JSON.parse() 解析会报错, 修复了这个错误.

之前对于无效的 UTF-16 字符编码, JSON.stringify() 会被替换为无意义的特殊字符, 现在修复了这个错误:

JSON.stringify("\uD83D")
// 之前: '"�"'
// 目前: '"\\ud83d"'

Array.sort()更加稳定

之前的规范允许不稳定的排序算法如快排, 目前主流浏览器都使用稳定的排序算法, 对于传入的比较算法计算结果等于 0 的情况也能保持顺序稳定.

Function.toString() 重新修订

之前的 Function.toString() 只返回函数主体, 丢失了原始的注释和空格等信息.

现在 Function.toString() 返回的结果与函数编写的一致.

ES 2018

for await...of

用于遍历异步可迭代对象(也可遍历同步可迭代对象).

需要放在 async function 内部.

// 一个异步可迭代对象
const asyncIterable = {
  [Symbol.asyncIterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return Promise.resolve({ value: this.i++, done: false })
        }

        return Promise.resolve({ done: true })
      },
    }
  },
}
// 遍历异步可迭代对象
;(async function () {
  for await (n of asyncIterable) {
    console.log(n)
  }
})()

Promise.finally()

当 Promise 执行结束时, 无论结果是 fulfilled 还是 rejected, 都会执行 finally 回调.

new Promise(...)
    .then(...)
    .catch(...)
    .finally(...);

Object Rest Properties

对象剩余属性:

let obj = { a: "aa", b: 30, c: true, d: "" }
let { a, b, ...others } = obj
a // "aa"
b // 30
others // { c: true, d: "" }

New RegExp Features

新增 4 个 RegExp 新特性:

  • Unicode 属性转义 \p{...}
  • 后行断言(lookbehind assertion) (?<=...) (?<!)
  • 可命名捕获组 (?<name>...)
  • s (dotAll) Flag, 使用 s 标志激活 . 字符匹配任意一个字符(dotAll 模式)

ES 2017

String Padding

使用另一个字符串(重复)填充当前字符串, 以达到指定长度

  • padStart 左侧填充
  • padEnd 右侧填充
"abc".padStart(10) // "       abc", 默认填充空格
"abc".padEnd(10) // "abc       ", 右侧填充
"abc".padStart(10, "foo") // "foofoofabc", 用指定字符重复填充
"abc".padStart(5, "12345") // "12abc", 多余字符丢弃
"abc".padStart(2) // "abc", 若长度小于当前字符串则不变

Object.entries()

返回对象自身(不包括原型链)可枚举属性的键值对数组:

let o = { a: "aaa", b: 20 }
console.log(Object.entries(o)) // [['a', 'aaa'], ['b', 20]]
for (let [key, value] of Object.entries(o)) {
  console.log(`${key}: ${value}`)
}

for..in 循环的顺序一致, 但 for..in 循环会枚举原型链中的属性.

Object.values()

返回对象自身的所有可枚举属性值的数组:

let o = { a: "aaa", b: 20 }
console.log(Object.values(o)) // ["aaa", 20]

Async Functions

使用 async await 关键字更简洁地书写基于 Promise 的异步行为.

Object.getOwnPropertyDescriptor()

获取对象的一个自有属性的属性描述符:

const obj = { a: "aaa" }
Object.getOwnPropertyDescriptor(obj, "a")
// {value: 'aaa', writable: true, enumerable: true, configurable: true}

函数参数列表中的尾随逗号

允许在函数声明和函数调用的参数列表中使用尾随逗号:

const func = (v1, v2,) => {...};
func("t1", "t2",);

同时也支持对象字面量和数组字面量后的逗号.

SharedArrayBuffer 和 Atomics

WebWorkers 可以创建多线程程序, 使用 SharedArrayBuffer 创建共享数组缓冲区, 使得多个 workers 和主线程之间可以共享数据.

全局对象 Atomics 提供了一组静态方法对 SharedArrayBufferArrayBuffer 进行原子操作, 使得多个线程可以按规定顺序安全地读写同一位置的数据.

为了防止 Spectre 漏洞, 所有主流浏览器默认禁用 SharedArrayBuffer .

ES 2016

求幂运算符 **

let x = 2 ** 5;

等价于 Math.pow(x, y)

“幂等”运算符 **= , 如:

let x = 5;
x **= 2; // 相当于x = x ** 2

Array.includes()

let arr = ["1", "2", "3"];
arr.includes("1");  // true
arr.includes("4");  // false

ES6 (ES2015)

关键字和类型

  • letconst 声明
  • 箭头函数
  • for/of 遍历可迭代的数据结构: Array, String, Map, NodeList 等

    • 区分 for/in : 遍历所有可枚举属性, 适用于遍历 Object 属性
  • Map 对象
  • Set 对象
  • class "面向对象"相关方法实现
  • Promise
  • Symbol 基本类型

Function

  • Function 参数默认值 function fn(x = 2){...}
  • Function 剩余参数 function fn(a, b, ...others) {...}

String

  • String.includes()
  • String.startsWith() String.endsWith()

Array

  • Array.from() 从具有长度或可迭代的对象创建数组, 如 Set, String 等
  • Array.keys() 返回数组的索引迭代器
  • Array.find() Array.findIndex() 返回满足测试函数的第一个元素 / 元素索引.

Math

  • Math.trunc() 截取整数部分
  • Math.sign() 返回数字的符号, 取值: 1, -1, 0, -0, NaN, 传入参数会被隐式转换为数字.
  • Math.cbrt() 立方根
  • Math.log2() Math.log10()

Number

  • Number.EPSILON 最小精度值, 两数之差小于此值可认为两数相等.
  • Number.MIN_SAFE_INTEGER Number.MAX_SAFE_INTEGER 安全整数范围
  • Number.isInteger() Number.isSafeInteger()

Global Methods

  • isFinite() 参数为 InfinityNaN 是返回 false, 其他情况为 true
  • isNaN()

Object

  • Object.entries() 返回对象可枚举属性的键值对数组

    const o = { a: "aa", b: 2 };
    console.log(Object.entries(o));  // [["a", "aa"], ["b", 2]]
    

JavaScript Modules

JavaScript modules - JavaScript | MDN


Profile picture

佚树 的个人博客

关于前端、音乐与生活