ES7 === ES2016
- 新增数组的include方法
- 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
- Async 函数呈现更清晰的Promise语法 async await
- Object.values() 返回一个给给定对象自己所有可枚举属性值的数组。
- Object.entries() 转成键值对数组
- String.prototype.padStart(targetLength, [padString])与String.prototype.padEnd 前后补全
- Object.getOwnPropertyDescriptors() 获取自身描述符;
- 结尾允许逗号,数组定义和函数参数列表
- 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
- 新增异步迭代器 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();
- Promise.finally();
- Rest/Spread 属性 Rest: 剩余参数,将剩下的参数“凝聚”为单个元素。 Spread: 扩展运算符,将数组展开为其中的各个元素。 用于对象浅拷贝 深拷贝:在计算机中开辟了一块新的内存地址用于存放复制的对象。 浅拷贝:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用。也就是,浅拷贝仅仅只是指向被复制的内存地址,如果原地址中对象被改变了,那么浅拷贝出来的对象也会相应改变。 区别:浅拷贝只拷贝一层,深层次的对象级别就是拷贝引用;深拷贝就是拷贝多层,每一级别的数据都会被拷贝。
- 正则表达式命名捕获组
// ?<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>`);
- 正则表达式反向断言 先行断言:是当扫描指针位于某处时,引擎会尝试匹配指针还未扫过的字符,先与指针到达该字符。 后行/反向断言:引擎会尝试匹配指针已扫过的字符,后于指针到达该字符。
// 先行断言 (?=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));
- dotAll 模式 正则表达式中的
.匹配除回车外的任何单字符,标记s改变这种行为,允许终止符的出现。
const str = 'yi\ndeng';
console.log(/yi.deng/.test(str)); // false
console.log(/yi.deng/s.test(str));
- 汉字匹配
// 以前匹配
const str = '贝展鹏是猪';
const oldReg = /[\u4e00-\u9fa5]/;
oldReg.test(str); // true
const newReg = /\p{Script=Han}/u;
newReg.test(str);
- 非转移序列的模板字符串
ES10 === ES2019
- 新增了Array的flat()和flatMap()方法
- flat(),默认拉平一维数组,可以传参数。可以去除数组中的空项。
- flatMap(),只支持拉平一维数组,用于遍历。
const arr = [1,2,,,5];
console.log(arr.flat()); // [1,2,5]
- 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}
- trimStart()和trimEnd() 分别去除字符串首尾空白字符
- Symbol.prototype.description() 返回 Symbol 对象的可选描述的字符串
const desc = Symbol('描述');
console.log(desc.description);
- Catch 参数可以省略
// 之前
try {
} catch(e) {
}
// 现在
try {
} catch {
}
- 行分隔符和段分隔符 以前,这些符号在字符串文字中被视为行终止符,因此使用它们会导致SyntaxError异常。
// 草案阶段,想要解决的问题
const json = '{"name": "kk\n2333"}';
console.log(json);
JSON.parse(json);
- 更加友好的JSON.stringify
- 支持的Unicode字符变多了
- 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}
]
- 新增 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();
}