今天这篇文章的灵感来自于日常的项目开发,「 我以为vue项目中已经添加了对可选链的支持,但在使用的时候会报错,所以我更新了cli,发现最新版的cli已经对babel进行了更新 ,也就是对ES的新的一些特性已支持 」。
简单的归纳了几个点:
- Array新方法find、findIndex、includes、flat等
- Object新方法entries、fromEntries、Object.getOwnPropertyDescriptors等
- String新方法padStart、padStart、trimStart、trimEnd、
- for await of
- Function.prototype.toString
接下来展开讨论一下。
Array
在项目中我们常常会遇到对数组的操作是
- 数组中判断是否有该字段
- 在数组中找到某一对象
- 多维数组平铺
- 拼接、过滤、排序、裁剪、填充等
在ES6中我们判断一个字符串中是否包含某一个字符,我们可以用includes:
- let str = '惊天码盗';
- str.includes('惊天');
- // true
而在ES7中也加入了对数组的支持
- const arr = [1, 3, 5, 2, '8', NaN, -0, undefined]
- arr.includes(1) // true
- arr.includes(1, 2) // false 该方法的第二个参数表示搜索的起始位置,默认为 0
- arr.includes('1') // false
- arr.includes(NaN) // true
- arr.includes(+0) // true
- arr.includes(undefined) // true
在业务代码中遇到最多的就是在数组中找到某一对象
- const list = [{ id: 1, name: 'Jok' }, { id: 2, name: 'Tom' }]
- // 判断list是否存在Tom
- const isHasTome = list.some(e => e.name == "Tom");
- // true
- const jokItem = list.find(e => e.name == "Tom");
- // { id: 2, name: 'Tom' }
- const jokIndex = list.findIndex(e => e.name == "Tom");
- // 1
- // 检查数组所有元素是否符合指定条件
- const hasPropToName = list.every(e => e.name)
- // true 检查每一项是否有name属性
在ES10中新增了一个flat方法,将多维数组打平:
- const arr = [1, 2, [3, [4, 5], 6], 7]
- arr.flat();
- // [1, 2, 3, [4, 5], 6, 7]
- arr.flat(2);
- // [1, 2, 3, 4, 5, 6, 7]
- //arr.flat(depth)
- // depth 是指定要提取嵌套数组的结构深度,默认值为 1
在ES6中还有一个比较有意思的API,就是entries
- // 数组迭代器
- const iterator = list.entries()
- iterator.next();
- // { done: false, value:[ 0, { id: 1, name: 'Jok' }] }
- iterator.next();
- // { done: false, value:[ 1, { id: 2, name: 'Tom' }] }
- iterator.next();
- // { done: true, value: undefined}
有点类似generator函数。
- // 处理promise
- const promiseCase = (p) => {
- return new Promise(function (resolve, reject) {
- setTimeout(function () {
- resolve(`${p}成功`); //代码正常执行!
- }, 250);
- });
- }
- const asyncList = [promiseCase('p1'), promiseCase('p2'), promiseCase('p3')];
- const iterator = asyncList.entries();
- // undefined
- for (let e of iterator) {
- console.log(e);
- e[1].then(
- res=>console.log(res)
- )
- }
- // [0, Promise]
- // [1, Promise]
- // [2, Promise]
- // p1成功
- // p2成功
- // p3成功
Object
ES5引入了Object.keys返回健名。紧跟着ES8引入了Object.values和Object.entries,作为遍历一个对象的手段,供for of使用。
- const obj = { foo: 'bar', baz: 42 };
- Object.keys(obj)
- // ["foo", "baz"]
- Object.values(obj)
- // ["bar", 42]
- const objEntries = Object.entries(obj)
- // [["foo", "bar"], ["baz", 42]]
- Object.fromEntries(objEntries)
- // {foo: "bar", baz: 42}
也可以用entries来判断对象中某些值的对比:
- const obj = {
- a: 21,
- b: 22,
- c: 23
- }
- let res = Object.fromEntries(Object.entries(obj).filter(([a, b]) => b > 21))
- console.log(res)
- // {b: 22, c: 23}
ES5 的 Object.getOwnPropertyDescriptor() 方法会返回某个对象属性的描述对象(descriptor)。ES8 引入了 Object.getOwnPropertyDescriptors() 方法,返回指定对象所有自身属性(非继承属性)的描述对象。
Object.assign无法正确拷贝get属性和set属性,Object.getOwnPropertyDescriptors() 方法配合 Object.defineProperties() 方法,就可以实现正确拷贝。
- const source = {
- set foo (value) {
- console.log(value)
- },
- get bar () {
- return '浪里行舟'
- }
- }
- const target1 = {}
- Object.assign(target1, source)
- console.log(Object.getOwnPropertyDescriptor(target1, 'foo'))
- // undefined
- const target2 = {}
- Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source))
- console.log(Object.getOwnPropertyDescriptor(target2, 'foo'))
- // set: ƒ foo(value)
String
在 ES8 中 String 新增了两个实例函数 String.prototype.padStart 和 String.prototype.padEnd,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。
- String.padStart(targetLength,[padString])
- // targetLength(必填): 当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
- // padString(可选): 填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,此参数的缺省值为 " "。
- 'x'.padStart(4, 'ab') // 'abax'
- 'x'.padEnd(5, 'ab') // 'xabab'
在ES10中新增了两个移除开头和结尾的空格。
- let str = ' 惊天 码盗 '
- str.trimStart(); // str.trimLeft();
- // '惊天 码盗 '
- str.trimEnd(); // str.trimRight();
- // ' 惊天 码盗'
- str.trim();
- // '惊天 码盗'
- str.replace(/\s+/g, '') ;
- // '惊天码盗'
for await of
for of方法能够遍历具有 Symbol.iterator 接口的同步迭代器数据,但是不能遍历异步迭代器。ES9 新增的 for await of 可以用来遍历具有 Symbol.asyncIterator 方法的数据结构,也就是异步迭代器,且会等待前一个成员的状态改变后才会遍历到下一个成员,相当于 async 函数内部的 await。
我想大家基本都写过类似这样的代码:
- const promiseCase = (p) => {
- return new Promise(function (resolve, reject) {
- setTimeout(function () {
- resolve({
- code: 0,
- name: `${p}`
- }); //代码正常执行!
- }, 250);
- });
- }
- const asyncList = [promiseCase('p1'), promiseCase('p2'), promiseCase('p3')];
- asyncList.forEach(async (e) => {
- const data = await e;
- console.log(data)
- })
- // {code: 0, name: "p1"}
- // {code: 0, name: "p2"}
- // {code: 0, name: "p3"}
现在可以这样写:
- async function test () {
- for await (let item of asyncList) {
- console.log(Date.now(), item)
- }
- }
- test()
- // 1614935341100 {code: 0, name: "p1"}
- // 1614935341100 {code: 0, name: "p2"}
- // 1614935341100 {code: 0, name: "p3"}
Function.prototype.toString
ES2019 中,Function.toString() 发生了变化。之前执行这个方法时,得到的字符串是去空白符号的。
而现在,得到的字符串呈现出原本源码的样子:
- function sum(a, b) {
- return a + b;
- }
- console.log(sum.toString());
- // function sum(a, b) {
- // return a + b;
- // }
本文转载自微信公众号「惊天码盗」,可以通过以下二维码关注。转载本文请联系惊天码盗公众号。