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)
})()