ES7 === ES2016

  1. 新增数组的include方法
  2. Math.pow的简写语法(求幂)
const arr = [1, 2, 3];
console.log(arr.indexOf(1) !== -1);
console.log(arr.includes(1));

// 输出2的3次方
console.log(Math.pow(2, 3)); 
console.log(2 ** 3);

ES8 === ES2017

  1. Async 函数呈现更清晰的Promise语法 async await
  2. Object.values() 返回一个给给定对象自己所有可枚举属性值的数组。
  3. Object.entries() 转成键值对数组
  4. String.prototype.padStart(targetLength, [padString])与String.prototype.padEnd 前后补全
  5. Object.getOwnPropertyDescriptors() 获取自身描述符;
  6. 结尾允许逗号,数组定义和函数参数列表
  7. SharedArrayBuffer 与 Atomics 用于共享内存位置读取和写入 -> 给js带来了多线程的功能,高级特性,js引擎核心改进
    • Atomics 对象提供了一组静态方法用于对 SharedArrayBuffer 对象进行原子操作。
/**
* 操作异步代码
* 1. 嵌套回调
* 2. Promise
* 3. Generators
*/

async function fn () {
    await Promise.resolve();
    console.log(1);
}

async function add(num) {
    const a = 1;
    return num + a;
}

const obj = {name: 'kk', age: 16};

// 拿键值对的值
console.log(Object.keys(obj).map(item => obj[item]));
console.log(Object.values(obj));
console.log(Object.entries(obj));

// 前面补0
console.log('123'.padStart(5, '0'));

// 
const obj = {
    name: 'kk',
    get fn() {
        return "fn";
    }
}
console.log(Object.ggetOwnPropertyDescriptors(obj));

ES9 === ES2018

  1. 新增异步迭代器 Asyncchronous Iterator 异步执行语句 for ... await ...of, Async generator 生成器: 跟函数很像,可以在执行过程中返回多次。看起来是同步,其实是异步。 迭代器: 等同于遍历器,实现可循环遍历获取集合中个数据项。
// 同步迭代器
function* fn() {
    yield 1;
    yield 2;
    yield 3;
}
const a = fn();
a.next(); // {value: 1, done: false}
a.next(); // {value: 2, done: false}
a.next(); // {value: 3, done: false}
a.next(); // {value: undefined, done: true}

// 异步迭代器
async function* fn () {
    yield await Promise.resolve(1);
    yield await Promise.resolve(2);
    yield await Promise.resolve(3);
}
const async1 = fn();
async function fn1 () {
    for await(const val of async1) {
        console.log(val);
    }
}
fn1();
  1. Promise.finally();
  2. Rest/Spread 属性 Rest: 剩余参数,将剩下的参数“凝聚”为单个元素。 Spread: 扩展运算符,将数组展开为其中的各个元素。 用于对象浅拷贝 深拷贝:在计算机中开辟了一块新的内存地址用于存放复制的对象。 浅拷贝:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用。也就是,浅拷贝仅仅只是指向被复制的内存地址,如果原地址中对象被改变了,那么浅拷贝出来的对象也会相应改变。 区别:浅拷贝只拷贝一层,深层次的对象级别就是拷贝引用;深拷贝就是拷贝多层,每一级别的数据都会被拷贝。
  3. 正则表达式命名捕获组
// ?<name>
const dateStr = '2020-06-05';
const reg = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<date>[0-9]{2})/;
const res = reg.exec(dateStr);
console.log(res.groups.year, res.groups.month, res.groups.date);

// replace 06-05-2020
const newDate = dateStr.replace(reg, `$<month>-$<date>-$<year>`);
  1. 正则表达式反向断言 先行断言:是当扫描指针位于某处时,引擎会尝试匹配指针还未扫过的字符,先与指针到达该字符。 后行/反向断言:引擎会尝试匹配指针已扫过的字符,后于指针到达该字符。
// 先行断言 (?=pattern)
const str = '$56789';
const reg = /\D(?=\d+)/;
const result = reg.exec(str);
console.log(result[0]); // $

// 后行断言 反向断言
const reg1 = /(?<=\D)\d+/;
console.log(reg1.exec(str));
  1. dotAll 模式 正则表达式中的. 匹配除回车外的任何单字符,标记s改变这种行为,允许终止符的出现。
const str = 'yi\ndeng';
console.log(/yi.deng/.test(str)); // false
console.log(/yi.deng/s.test(str));
  1. 汉字匹配
// 以前匹配
const str = '贝展鹏是猪';
const oldReg = /[\u4e00-\u9fa5]/;
oldReg.test(str); // true

const newReg = /\p{Script=Han}/u;
newReg.test(str);
  1. 非转移序列的模板字符串

ES10 === ES2019

  1. 新增了Array的flat()和flatMap()方法
    • flat(),默认拉平一维数组,可以传参数。可以去除数组中的空项。
    • flatMap(),只支持拉平一维数组,用于遍历。
const arr = [1,2,,,5];
console.log(arr.flat()); // [1,2,5]
  1. Object.fromEntries() 把键值对列表转化为一个对象
// Map 转化为 Object
const map = new Map([
    ['foo', 'bar'],
    ['baz', 42]
]);
console.log(Object.fromEntries(map)); // {foo: "bar", baz: 42}

// Array 转换成Object
const arr = [
    ['foo', 'bar'],
    ['baz', 42]
];
console.log(Object.fromEntries(arr)); // {foo: "bar", baz: 42}
  1. trimStart()和trimEnd() 分别去除字符串首尾空白字符
  2. Symbol.prototype.description() 返回 Symbol 对象的可选描述的字符串
const desc = Symbol('描述');
console.log(desc.description);
  1. Catch 参数可以省略
// 之前
try {

} catch(e) {

}

// 现在
try {

} catch {

}
  1. 行分隔符和段分隔符 以前,这些符号在字符串文字中被视为行终止符,因此使用它们会导致SyntaxError异常。
// 草案阶段,想要解决的问题
const json = '{"name": "kk\n2333"}';
console.log(json);
JSON.parse(json);
  1. 更加友好的JSON.stringify
  • 支持的Unicode字符变多了
  1. Array.prototype.sort();
  • 小于10 插入排序 快速排序不稳定的排序 O(n^2)
  • 新的v8 稳定排序 O(nlogn)
const arr = [
    {name: 'w', age: 18},
    {name: 'kk', age: 4},
    {name: 'bb', age: 4}
];

arr.sort((a, b) => a.age - b.age);
console.log(arr);

// 非稳定排序,kk bb的位置更改
[
    {name: 'bb', age: 4},
    {name: 'kk', age: 4},
    {name: 'w', age: 18}
]

// 稳定排序
[
    {name: 'kk', age: 4},
    {name: 'bb', age: 4},
    {name: 'w', age: 18}
]
  1. 新增 Function.prototype.toString() 标准化,返回精确字符,包括空格和注释
function /*注释*/ fn  /*注释*/ () {}

// 之前
console.log(fn.toString()); // function fn() {}

// 现在
console.log(fn.toString()); // function /*注释*/ fn  /*注释*/ () {}

ES11 === ES2020

?? 空值合并

如果你在赋值的时候想要一个默认值(如果当前的值为null 或 undefined), 则可以使用??

var person = {};
var name = person.fullName ?? 'anonymous'; // 此时name的值为 anonymous


person.fullName = 'kk';
name = person.fullName ?? 'anonymous'; // 此时name的值为 kk

思考🤔 -> 用 || 可以吗?

const test = {count: 0};
const num = test.count ?? 50; // value is 0
const numWrong = test.count || 50; // value is 50 

空字符串'', 0, false, null, undefined, NaN时,使用 || 时,都会用后面的值。 而 ??, 只检查null 和 undefined

可选链

如果要使用多层嵌套中的属性,在以前就必须检查他们是否为 null 或 undefined,以避免代码崩溃。

现在访问这些属性之前可以用?.,这样就可以在值不为 null 或 undefined时,使用 ?. 后面的代码。

const person = {
    user: {
        name: 'kk',
        age: 16,
        sex: 'female'
    }
}

// old javascript
if (person && person.user && person.user.name === 'kk') {
    console.log(`she age is ${person.user.age}`);
}

// ES11
if (person?.user?.name === 'kk') {
    console.log(`she age is ${person.user.age}`);
}

Promise.allSettled

我们知道在Promise.all() 中,如果其中任何一个请求失败,将会引发异常,需要单独去做catch处理。

那么现在使用Promise.allSettled,无论是成功还是失败,都会返回

const promises = [Promise.resolve(1), Promise.reject(2)];
const [result1, result2] = await Promise.allSettled(promises);

// result1  -> {status: "fulfilled", value: 1}
// result2 -> {status: "rejected", reason: 2}

matchAll

如果要用正则表达式来查找所有的匹配项,可以用match来获取所有子字符串。

但是如果又要有子字符串,又要索引,那么此时可以用matchAll进行匹配。

const matches = 'Here are some number: 12 8 3 66'.matchAll(/\d+/g);

for (const match of matches) {
    console.log(match);
}

// output
// ["5", index: 23, input: "Here are some numbers: 5 12 88", groups: undefined]
// ["12", index: 25, input: "Here are some numbers: 5 12 88", groups: undefined]
// ["88", index: 28, input: "Here are some numbers: 5 12 88", groups: undefined]

BigInt

BigInt 任意精度整数 第七种基本数据类型 - 可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt()。 - BigInt 和 Number 不是严格相等的,但是宽松相等的。

let num = 1n;
let num2 = 10n;
const bigIntNum = BigInt(10);
console.log(bigIntNum);             // 10n
console.log(bigIntNum === num2);    // true
console.log(typeof num);            // bigint
console.log(num == 1);              // true
console.log(num === 1);             // false

基本类型:Null, Undefined, String, Number, Boolean, Symbol, BigInt 引用类型: Object (引申出 Function, Array)

动态导入

以前只能在文件开头静态导入模块。

现在有了动态导入,可以按需在代码中的任何位置进行这种操作。import() 会与模块一起返回一个 Promise。

const module = await import('module');

模块命名空间导出

在大多数情况下,我们能够通过导入导出 JavaScript 模块来重命名模块的名称,就像这样:

import * as value from 'module';
import { value as v } from 'nodule';
export { v as value };

现在可以直接:

export * as someUtils from 'utils'; 

globalThis

标准化globalThis对象,在任何平台访问全局属性

console.log(globalThis);

// polyfill 
const getGlobal = function() {
    if (typeof self !== 'undefined') {
        return self;
    }
    if (typeof window !== 'undefined') {
        return window;
    }
    if (typeof global !== 'undefined') {
        return global;
    }
    throw new Error();
}
Last Updated:
Contributors: kk