又来复习啦 ES7、ES8、ES9 主要新特性
这里收集了某段时间前准备面试用的材料,方便更好的理解, 并整理出了一些 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
希望此文章能帮助到你~~~