(文豪镇楼)
在所有的社交媒体里满屏都是关于疫情的信息,让人焦虑。如果你一直处于这样的环境里,我劝你阳光一点, 认真的找点事来做,否则你很可能会被这种悲观的情绪打败。
所以我写了这篇文章。闲着也是闲着,不如来看es2020。
PS: 友情提示, 如果不想亲自配环境可以直接clone-npm install.然后跳到->步入正题, 一起操作.
配置环境
首先我们需要可以跑es2020的node环境,
// package.json
{
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/plugin-proposal-private-methods": "^7.8.3",
"@babel/plugin-syntax-bigint": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"core-js": "^3.6.4"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.8.4",
"@babel/register": "^7.8.3",
"babel-polyfill": "^6.26.0"
}
}
// .babellrc
{
"presets": ["@babel/preset-env"],
"plugins": [
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods",
"@babel/plugin-syntax-bigint",
"@babel/plugin-syntax-dynamic-import"
]
}
// index.js
var fs = require('fs');
var babelConfig = JSON.parse(fs.readFileSync('./.babelrc'));
require('@babel/register')(babelConfig);
require("babel-polyfill");
require('./src/index');
关于配置babel就是一个很大的话题了,貌似现在都是直接使用presets, 指定环境, 自己配就很少了....
环境的repo地址, 便于大家clone下来自己尝试.Dirty your hands.
步入正题
Private Class Variables-私有变量
熟悉面向对象的童鞋知道,在标准的面向对象语言里, 有个重要的特性就是私有变量。但是为了文章完整性还是解释一下。 私有变量只能在class的内部访问, 外部不可直接访问。也就是我可以通过class上的方法去访问私有变量, 而不可以直接使用点运算符去直接访问。看个例子就明白了。
class Person {
#id = 1;
getId() {
console.log(this.#id);
}
}
const b = new Person();
// 直接通过点运算符访问, 为undefined
console.log(b.id);
// 通过函数内部访问, 可访问到
console.log(b.getId())
promise.allSettled
是的, promise上新增了allSettled方法,差别在于, 对于reject的promise的处理方式。
Promise.all: 如果promise的list中存在一个reject, 那么promise.all会立即中断并且reject.em...打个比方就是一颗老鼠屎,坏了一锅粥.
Promise.allSettled: 如果promise的list某个promise状态为reject了, 没关系, 继续往下跑, 在最后返回一个数组, 包含所有list的结果, 不会在中间某个promise reject了, 而导致中断任务.
之前的业务有个场景,订单的单个增删改查现在要改成批量, 后端不给你接口.在这种情况下, 只能用单个接口来模拟批量行为, 但是很危险, 如果使用promise.all很容易出现我只成功了一部分,但是因为reject的行为, 你要在外层再套一层try-catch, 来handler错误的行为, 而且还没有反馈。很危险。(但是最后, 接口方提出接口都200保证在fetch层面不会抛出错误, 但是在后面排期把批量接口加上去了)
所以,Promise.allSettled的出现就很有必要了。来看个例子。
// promise.allSettled
const p1 = new Promise((res, rej) => setTimeout(() => res('resolve'), 1000));
const p2 = new Promise((res, rej) => setTimeout(() => res('reject'), 1000));
// 如果队列中任意一个promise返回reject, 则终止, throw error
Promise.all([p1, p2]).then(data => { console.log(data) });
// 等待所有的promise完成(无论成功失败), 返回一个promise结果的list
Promise.allSettled([p1, p2]).then(data => console.log(data));
Nullish Coalescing Operator-空位合并运算符
主要解决短路运算的问题, 而且更为严格, 值为null/undefined时才会去使用给定的值。
短路运算
const y = x || "defautl value"; // 如果x的值不存在那么就默认使用default value
空位合并运算符的出现改变了这种情况, 我们得到了【??】, 是的, 空位运算符就是??所以,以上的语法可以改写为.但是要注意, 和 || 操作符不一样的是, 必须要为null/undefined的时才会赋值default value.所以类似false, 0, 空字符串这些是不会触发的。更为严谨了。
const y = x ?? "default value";// default value
console.log("??", false ?? "default value"); // false
console.log("??", 0 ?? "default value"); // 0
console.log("??", '' ?? "default value"); // ''
Optional Chaining Operator-可选链式运算
解决了复杂嵌套对象取值问题。对于复杂对象, 我们都要写很多防御性的代码, 来与“TypeError: Cannot read property 'code' of undefined”.作斗争.
let animal = {};
// old school
console.log(animal && animal.cat && animal.cat.name || "1");
// throw error 因为cat没有获取到
// console.log(animal.cat.name ?? "big cat");
// 不会throw error
console.log(animal?.cat?.name ?? "big cat");
console.log(animal?.cat?.age ?? 18);
big Int
众所周知, js对于浮点的运算很是让人难过.才会出现类似.1 + .2 !== .3这种问题, 而bigInt的出现让你在将来面对面试官提出的精度问题拿出最为标准的解决方案.
const maxNumber = Number.MAX_SAFE_INTEGER;
console.log(.1 + .2 !== .3);
console.log(maxNumber); // 9007199254740991
console.log(maxNumber + 1);// 9007199254740992
console.log(maxNumber + 2); // 9007199254740992
// 那么bigInt的出现就解决这些问题
// 定义bigInt: 在数字后面加“n”
const bigNumber = 100000000000000000000000000000n;
console.log(bigNumber * 2n);// 200000000000000000000000000000n
Dynamic Import-动态导入
在webpack4的时候, shakeTree就已经内置, 默认开启。按需加载对于体积日益增长的前端工程来说真的很重要。
我们日常使用的es6语法已经支持模块化的去导入,而动态导入则是在代码执行过程中使用async + import语法进行动态的导入一些需要的模块。
// count.js
const plusSelf = (n) => n + 1;
export { plusSelf };
// index.js
const add1 = async (n) => {
if (typeof n === 'number') {
const { plusSelf } = await import('./count.js');
console.log(plusSelf(n));
}
}
add1(5); // 6
(完)
满地打滚求三连: 求点赞, 求start, 求关注.
文章引用: