ES2020新特性

一、Promise.allSettled

Promise.all 具有并发执行异步任务的能力,但最大的问题就是只要有一个任务出现异常(reject),所有的任务都会直接走异常reject状态,走catch回调;
Promise.allSettled 如果并发任务中,无论一个任务正常或者异常,都会返回对应的的状态(fulfilled 或者 rejected)与结果(业务value 或者 拒因 reason,在 then 里面通过 filter 来过滤出想要的业务逻辑结果,这就能最大限度的保障业务当前状态的可访问性。

Promise.allSettled([
	Promise.reject({code: 500, msg: “接口挂了"});
	Promise.resolve({code: 200, data: []});
	Promise.resolve({code: 200, data: []})
]).then((res) => {
	// res --> 返回 [{status: "reject", reson: {}},{status: "fulfilled", value: {}},{status: "fulfilled", value: {}}]
	// 获取有效数据
	let data = res.filter(el => el.states !== "reject")
})

二、可选链(optional chaining)

开发中,使用某字段的时必不可少的需要做前置校验;

let name = user && user.info && user.name;
let fun = user && user.info && user.info.doSamething();
// 使用 optional chaining  ?表示如果问号左边表达式有值, 就会继续查询问号后面的字段
let nameNew = user?.info?.name;
let funNew = user?.info?.doSamethiing?.();

三、空值合并运算符(Nullish coalescing Operator)

开发中,查询某字段不存在则会设置一个默认值

let name = (user && user.name) || "学生";
// 使用空值合并运算符 ?? 
let nameNew = `${user.name}` ?? "学生";

空值合并运算符 与 可选链 相结合,可以很轻松处理多级查询并赋予默认值问题。

let name = user?.info?.name ?? "学生"

四、dynamic-import 按需加载

前端打包资源越来越大,打包成几M的JS资源已成常态,而往往前端应用初始化时根本不需要全量加载逻辑资源,为了首屏渲染速度更快,很多时候都是按需加载。而这些按需执行逻辑资源都体现在某一个事件回调中去加载

el.onclick = () => {
	import(`/path/test.js`).then((module) => {
		module.doSomething()
	}).catch((err) => {})
}

五、globalThis

Javascript 在不同的环境获取全局对象有不通的方式,node 中通过 global, web中通过 window, self 等,有些甚至通过 this 获取,但通过 this 是及其危险的,this 在 js 中异常复杂,它严重依赖当前的执行上下文,这些无疑增加了获取全局对象的复杂性。过去获取全局对象,可通过一个全局函数

var getGlobal = function() {
	if(typeof self !== "undefined") return self;
	if(typeof window !== "undefined") return window;
	if(typeof global !== "undefined") return global;
	throw new Error("unable to locate global object")
}
var globals = getGlobal();

而 globalThis 目的就是提供一种标准化方式访问全局对象,有了 globalThis 后,你可以在任意上下文,任意时刻都能获取到全局对象。

六、BigInt 新的数据原始(primitive)类型

Js 中 Number类型只能安全的表示-(2^53-1)至 2^53-1 范的值,即Number.MINSAFEINTEGER 至Number.MAXSAFEINTEGER,超出这个范围的整数计算或者表示会丢失精度。
typeof 9007199254740993n; // -> ‘bigint’

七、 String.prototype.matchAll 获取到全局所有匹配项,包括子项

var str = '<text>JS</text><text>正则</text>';
var str.matchAll(/<\w+>(.*?)<\/\w+>/g);
for(const match of allMatchs){
	console.log(match);
}
/*第一次迭代返回:
[
    "<text>JS</text>",
    "JS",
    index: 0,
    input: "<text>JS</text><text>正则</text>",
    groups: undefined
]
第二次迭代返回:
[
    "<text>正则</text>",
    "正则",
    index: 15,
    input: "<text>JS</text><text>正则</text>",
    groups: undefined
]
*/

ES7 async、await 异步执行
题1:输出0,1,2,3,4
解法1:IIFE立即执行函数加形成闭包

for(var i=0;i<5;i++){
    (function (i) {
        setTimeout(function () {
            console.log(i) // 0,1,2,3,4
        }, 1000)
    })(i)
}

解法2:利用JS的基本类型中参数传递是按值传递的特征

var  output = function (i) {
    setTimeout(function () {
        console.log(i)   // 0,1,2,3,4
    }, 1000)
};
for (var i = 0; i < 5; i++) {
    output(i)
}

解法3:利用ES6的let块级作用域

for(let i=0;i<5;i++){
    setTimeout(function () {
        console.log(i)
    }, 1000)
}

题2:输出0,1,2,3,4,5 要求立即输出0,后每隔一秒输出后面的数字
解法1:利用ES6的新特性Promise

const tasks = [];
for(var i=0;i<5;i++){
    ((j) => {
        tasks.push(new Promise((resolve) => {
        setTimeout(function () {
            console.log(j)     //
            resolve() 
        }, 1000*j)  //定时器的时间逐步增加
    }))
    })(i)
}
Promise.all(tasks).then(() => {
    setTimeout(function(){
        console.log(i)
    },1000)
}).catch(() => {})

解法2:利用ES6的新特性Promise

const tasks = [];  //存放异步操作的Promise
const output = (i) => new Promise((resolve) => {
    setTimeout(function(){
        console.log(i)   //0,1,2,3,4
        resolve()
    },1000*i)
})
//生成全部的异步操作
for(var i=0;i<5;i++){
    tasks.push(output(i))
}
//异步操作完成后,输出最后的i的值
Promise.all(tasks).then(() => {
    setTimeout(function(){
        console.log(i)  //5
    },1000)
})

解法3:利用ES7中的async、await

const sleep = (times) => new Promise((resolve) => {
    setTimeout(resolve, times)
})

(async () => {    //声明即执行的async 函数表达式
    for(var i = 0;i<5;i++){
        await sleep(1000);
        console.log(i)
	}
	await sleep(1000);
    console.log(i)
})()