「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」
这里收集了某段时间前准备面试用的材料,方便更好的理解, 并整理出了一些 ES7至ES9 的常用新特性,在这做下分享,巩固记忆。
ES7 新特性
includes()-判断数组是否含有特定的值
如果需要判断数组中是否含有某个特定的值,以往可能更多的是使用indexOf
的方式,有则返回查找值的下标,没有则返回-1,这在判断值是否存在,并需要获取值下标的场景比较友好。
const arr = [1, 2, 3]
arr.indexOf(2) // 1
而includes
则直接返回 Boolean 值,不返还值的下标,更纯粹的用于判断值的数组包含与否。
const arr = [1, 2, 3]
arr.includes(2) // true
arr.includes(4) // false
**
-指数操作符
如果需要进行指数的计算,在以往需要怎么实现?
例如,输出2的10次方,除了自定义递归方法去实现之外,可以用Math.pow
函数实现。
Math.pow(2, 10) // 1024
在 ES7 中,新增了指数的操作运算符**
,可以更方便地去进行指数运算。
2**10 // 1024
ES8 新特性
async/await-异步操作关键字
为了解决回调地狱的问题,Promise 是个不错的解决方案,但在处理复杂流程的场景,Promise 欠缺了一定的语义化,各个流程通过 .then 连接,读起代码来较为恶心。
设想一个实际场景:用户登录的操作,在用户请求完登录接口并验证通过后,再请求用户信息接口获取用户信息,Promise 实现方式如下:
userLogin(data)
.then(res=>{
return getUserInfo(res.token)
})
.then(res=>{
console.log(res)
})
.catch(err=>{
console.error(err)
})
如果流程更复杂的话,then 连接会更多,直到最后的 catch,这对于代码维护增加了不少阅读成本,不能够很好的表达执行流程。
于是便有了 async/await, 既可以用同步代码的方式去实现,又可以异步处理的关键字,还支持 try catch 捕获异常,两者不能脱离开来单独使用,await 后面一定得是 Promise 对象,否则,它将会自动的包装成一个 Promise 对象。
使用 async/await 的实现如下:
try {
let loginRes = await userLogin(data)
let res = await getUserInfo(loginRes.token)
console.log(res)
} catch (err) {
console.error(err)
}
values()/entries()-遍历对象新方式
ES7 新增了两个对象遍历方法,Object.values()
和Object.entries()
。
Object.values()
返回一个数组,包含对象自身的所有可遍历的属性值,示例:
const user = {name: "Sam", age: "25"}
Object.values(user) // ["Sam", "25"]
const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj) // ["b", "c", "a"]
需要注意的是,如果属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是 b、c、a。
Object.entries()
同样返回一个数组,包含对象自身的所有可比案例的键值和属性的成组,示例:
const user = {name: "Sam", age: "25"}
Object.entries(user) // [["name", "Sam"], ["age", "25"]]
const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(obj) // [["2", "b"], ["7", "c"], ["100", "a"]]
String padding-字符串填充
ES8 中对 String 新增了两个实例函数,分别是padStart
和padEnd
,意味将字符创添加到原始字符串的开头或结尾。
padStart
和padEnd
都允许接受两个参数:
- targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
- padString:(可选)填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,此参数的缺省值为 " "。 示例:
let str = 'Sam'
str.padStart(6,'its')// 'itsSam'
str.padEnd(6,'its')// 'Samits'
getOwnPropertyDescriptors-返回元素自身属性描述
如果想获取某个元素的自身属性描述,可以使用Object.getOwnPropertyDescriptors()
如果没有任何属性,则会返回空对象。
使用其可以解决Object.assign()
无法正确拷贝 get 和 set 的问题。
示例:
const obj = {name: "Sam"}
Object.getOwnPropertyDescriptors(obj)
// name:
// configurable: true
// enumerable: true
// value: "Sam"
// writable: true
// __proto__: Object
// __proto__: Object
ES9 新特性
for await of-异步迭代器
如果在 async/await
中使用循环中去调用异步函数,则不会正常执行,例如:
async function demo(arr) {
for (let i of arr) {
await handleDo(i);
}
}
该示例中,循环本身仍然保持着同步操作,并在内部异步函数之前,全部调用完成结束。
为了解决该问题,ES9 中引入了异步迭代器,允许在循环中去调用异步函数,示例:
async function demo(arr) {
for await (let i of arr) {
handleDo(i);
}
}
Promise.finally()-Promise 结束触发
当我们调用 Promise 时,下一个结果要么是.then()
,要么是失败触发.catch()
。这样导致有些代码需要在这两处重复写两遍,导致代码冗余,如果希望 Promise 不管是成功还是失败,都执行同样的代码,可以使用.finally()
,它允许你在执行结束后触发。
示例:
function login() {
userLogin()
.then(res=>{
console.log(res);
})
.catch(err => {
console.log(err);
})
.finally(() => {
console.log('finally');
});
}
Rest/Spread 属性
Rest参数语法允许我们将一个不定数量的参数表示为一个数组。示例:
restParam(1, 2, 3, 4, 5);
function restParam(p1, p2, ...p3) {
// p1 = 1
// p2 = 2
// p3 = [3, 4, 5]
}
ES9为对象解构提供了和数组一样的Rest参数和展开操作符,示例:
const Obj = {a: 1, b: 2, c: 3};
const { a, ...x } = Obj;// a = 1,x = { b: 2, c: 3 }
正则表达式新特性
s (dotAll) 标志
s(dotAll)flag 正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用 u 修饰符解决;另一个是行终止符, 如换行符 (n) 或回车符 (r), 这个可以通过 ES9 的 s(dotAll)flag,在原正则表达式基础上添加 s 表示:
console.log(/foo.bar/.test('foo\nbar')) // false
console.log(/foo.bar/s.test('foo\nbar')) // true
那如何判断当前正则是否使用了 dotAll 模式呢?
const re = /foo.bar/s // Or, `const re = new RegExp('foo.bar', 's');`.
console.log(re.test('foo\nbar')) // true
console.log(re.dotAll) // true
console.log(re.flags) // 's'
命名捕获组
在一些正则表达式模式中,使用数字进行匹配可能会令人混淆。因为美式英语中的日期表示法和英式英语中的日期表示法不同,所以很难区分哪一组表示日期,哪一组表示月份:
const re = /(\d{4})-(\d{2})-(\d{2})/;
const match= re.exec('2019-01-01');
console.log(match[0]); // → 2019-01-01
console.log(match[1]); // → 2019
console.log(match[2]); // → 01
console.log(match[3]); // → 01
ES9 引入了命名捕获组,允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。示例:
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = re.exec('2019-01-01');
console.log(match.groups); // → {year: "2019", month: "01", day: "01"}
console.log(match.groups.year); // → 2019
console.log(match.groups.month); // → 01
console.log(match.groups.day); // → 01
写在最后
写作不易,希望可以获得你的一个「赞」。如果文章对你有用,可以选择「收藏」。 如有文章有错误或建议,欢迎评论指正,谢谢你。❤️