ES9 - 新功能
在这里,我们将了解 ES9 中的新功能。让我们从了解异步生成器开始。
异步生成器和迭代
可以使用 async 关键字将异步生成器变为异步。定义异步生成器的 语法 如下所示 −
async function* generator_name() { //statements }
示例
以下示例展示了一个异步生成器,它在每次调用生成器的 next() 方法时返回 Promise。
<script> async function* load(){ yield await Promise.resolve(1); yield await Promise.resolve(2); yield await Promise.resolve(3); } let l = load(); l.next().then(r=>console.log(r)) l.next().then(r=>console.log(r)) l.next().then(r=>console.log(r)) l.next().then(r=>console.log(r)) </script>
上述代码的输出将如下所示 −
{value: 1, done: false} {value: 2, done: false} {value: 3, done: false} {value: undefined, done: true}
for await of loop
异步可迭代对象无法使用传统的 for..of loop 语法进行迭代,因为它们返回的是Promise。ES9 引入了 for await of loop 来支持异步迭代。
使用 for await of loop 的语法如下,其中,
每次迭代时,都会将不同属性的值分配给 variable,并且可以使用 const、let 或 var 声明变量。
- iterable −需要迭代其可迭代属性的对象。
for await (variable of iterable) { 语句 }
示例
以下示例显示了如何使用 for await of 循环来迭代异步生成器。
<script> async function* load(){ yield await Promise.resolve(1); yield await Promise.resolve(2); yield await Promise.resolve(3); } async function test(){ for await (const val of load()){ console.log(val) } } test(); console.log('end of script') </script>
上述代码的输出将如下所示 −
end of script 1 2 3
示例
以下示例使用 for await of 循环迭代数组。
<script> async function fntest(){ for await (const val of [10,20,30,40]){ console.log(val) } } fntest(); console.log('end of script') </script>
上述代码的输出将如下所示 −
end of script 10 20 30 40
Rest/Spread 属性
ES9 支持将 Rest 和 Spread 运算符与对象一起使用。
示例:对象和 Rest 运算符
以下示例显示了将 rest 运算符与对象一起使用。student 的 age 属性值被复制到 age 变量中,而其余属性的值则使用 rest 语法 `...` 复制到另一个变量中。
<script> const student = { age:10, height:5, weight:50 } const {age,...other} = student; console.log(age) console.log(other) </script>
上述代码的输出如下所示 −
10 {height: 5, weight: 50}
示例:对象和扩展运算符
扩展运算符可用于组合多个对象或克隆对象。如以下示例所示 −
<script> //spread operator const obj1 = {a:10,b:20} const obj2={c:30} //clone obj1 const clone_obj={...obj1} //combine obj1 and obj2 const obj3 = {...obj1,...obj2} console.log(clone_obj) console.log(obj3) </script>
上述代码的输出将如下所示 −
{a: 10, b: 20} {a: 10, b: 20, c: 30}
Promise:finally()
只要Promise得到解决,就会执行 finally(),无论其结果如何。此函数返回一个Promise。它可用于避免Promise的 then() 和 catch() 处理程序中的代码重复。
语法
下面提到的语法适用于函数 finally()。
promise.finally(function() { }); promise.finally(()=> { });
示例
以下示例声明了一个异步函数,该函数在延迟 3 秒后返回正数的平方。如果传递的是负数,该函数将抛出错误。无论Promise是被拒绝还是被解决,finally 块中的语句都会在任一情况下执行。
<script> let asyncSquareFn = function(n1){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ if(n1>=0){ resolve(n1*n1) } else reject('NOT_POSITIVE_NO') },3000) }) } console.log('Start') asyncSquareFn(10)//modify to add -10 .then(result=>{ console.log("result is",result) }).catch(error=>console.log(error)) .finally(() =>{ console.log("inside finally") console.log("executes all the time") }) console.log("End"); </script>
上述代码的输出将如下所示
Start End //after 3 seconds result is 100 inside finally executes all the time
模板字面量修订
从 ES7 开始,标记模板符合以下转义序列的规则 −
Unicode 转义序列使用 "\u" 表示,例如 \u2764\uFE0F
Unicode 代码点转义序列使用 "\u{}" 表示,例如 \u{2F>
十六进制转义序列使用 "\x" 表示,例如\xA8
八进制文字转义序列使用""表示,后跟一个或多个数字,例如 \125
在 ES2016 及更早版本中,如果将无效的转义序列与标记函数一起使用,则会引发语法错误,如下所示 −
//带有无效 unicode 序列的标记函数 myTagFn`\unicode1` // SyntaxError:格式错误的 Unicode 字符转义序列
但是,与早期版本不同,ES9 将无效的 unicode 序列解析为未定义,并且不会引发错误。这在下面的示例中显示 −
<script> function myTagFn(str) { return { "parsed": str[0] } } let result1 =myTagFn`\unicode1` //invalid unicode character console.log(result1) let result2 =myTagFn`\u2764\uFE0F`//valid unicode console.log(result2) </script>
上述代码的输出将如下所示 −
{parsed: undefined} {parsed: "❤️"}
原始字符串
ES9 引入了一个特殊属性 raw,可用于标记函数的第一个参数。此属性允许您访问输入的原始字符串,而无需处理转义序列。
示例
<script> function myTagFn(str) { return { "Parsed": str[0], "Raw": str.raw[0] } } let result1 =myTagFn`\unicode` console.log(result1) let result2 =myTagFn`\u2764\uFE0F` console.log(result2) </script>
上述代码的输出将如下所示 −
{Parsed: undefined, Raw: "\unicode"} {Parsed: "❤️", Raw: "\u2764\uFE0F"}
正则表达式功能
在正则表达式中,点运算符或句点用于匹配单个字符。. 点运算符 跳过换行符,如 , ,如下例所示 −
console.log(/Tutorials.Point/.test('Tutorials_Point')); //true console.log(/Tutorials.Point/.test('Tutorials Point')); //false console.log(/Tutorials.Point/.test('Tutorials Point')); //false
正则表达式模式表示为 / regular_expression /。 test() 方法采用字符串参数并搜索正则表达式模式。在上面的例子中,test() 方法 搜索以 Tutorials 开头,后跟任意单个字符并以 Point 结尾的模式。如果我们在 Tutorials 和 Point 之间的输入字符串中使用 或 ,则 test() 方法将返回 false。
true false false
ES9 引入了一个新标志 - DotAllFlag (\s),可与 Regex 一起使用来匹配行终止符和表情符号。以下示例 − 显示了这一点
console.log(/Tutorials.Point/s.test('Tutorials Point')); console.log(/Tutorials.Point/s.test('Tutorials Point'));
上述代码的输出将概要 −
true true
命名捕获组
在 ES9 之前,捕获组是通过索引访问的。ES9 允许我们为捕获组分配名称。相同的语法如下 −
(?<Name1>pattern1)
Example
const birthDatePattern = /(?<myYear>[0-9]{4})-(?<myMonth>[0-9]{2})/; const birthDate = birthDatePattern.exec('1999-04'); console.log(birthDate.groups.myYear); console.log(birthDate.groups.myMonth);
上述代码的输出如下所示 −
1999 04