教程 > ES6 教程 > ES6 高级 阅读:24

ES9 新特性

在这里,我们将了解 ES9 中的新特性。 让我们从了解异步生成器开始。


异步生成器和迭代

可以使用 async 关键字使异步生成器异步。 定义异步生成器的语法如下:

async function* generator_name() {
   //statements
}

示例

以下示例显示了一个异步生成器,它在每次调用生成器的 next() 方法时返回 Promise。

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))

上述代码输出结果如下

{value: 1, done: false}
{value: 2, done: false}
{value: 3, done: false}
{value: undefined, done: true}

for await of 循环

异步迭代不能使用传统的 for..of 循环语法迭代,因为它们返回 promise 。 ES9 引入了 for await of 循环来支持异步迭代。

下面给出了使用 for await of 循环的语法,其中,

  • 在每次迭代中,不同属性的值被分配给变量,并且变量可以用 constletvar 声明。
  • iterable - 要迭代其可迭代属性的对象。
for await (variable of iterable) {
   statement
}

示例

以下示例显示了使用 for await of 循环来迭代异步生成器。

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')

上述代码输出结果如下

end of script
1
2
3

以下示例使用 for await of 循环迭代数组。

async function fntest(){
    for await (const val of [10,20,30,40]){
         console.log(val)
    }
}
fntest();
console.log('end of script')

上述代码输出结果如下

end of script
10
20
30
40

Rest/Spread 属性

ES9 支持对对象使用 RestSpread 运算符。

示例:对象和 Rest 运算符

以下示例显示了对对象使用 rest 运算符。 student 的 age 属性的值被复制到 age 变量中,而其余属性的值被复制到使用 rest 语法“...”的另一个变量中。

const student = {
    age:10,
    height:5,
    weight:50
}
const {age,...other} = student;
console.log(age)
console.log(other)

上述代码输出结果如下

10
{height: 5, weight: 50}

示例:对象和展开运算符

展开运算符可用于组合多个对象或克隆对象。 这在以下示例中显示

//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)

上述代码输出结果如下

{a: 10, b: 20}
{a: 10, b: 20, c: 30}

Promise: finally()

finally() 会在 promise 完成时执行,无论其结果如何。 这个函数返回一个承诺。 它可用于避免 promise 的 then()catch() 处理程序中的代码重复。

语法

下面提到的语法是针对函数 finally() 的。

promise.finally(function() {
});
promise.finally(()=> {
});

示例

以下示例声明了一个异步函数,该函数在延迟 3 秒后返回正数的平方。 如果传递负数,该函数将抛出错误。 finally 块中的语句在任何一种情况下都会执行,无论 promise 是被拒绝还是已解决。

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");

上述代码输出结果如下

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: malformed Unicode character escape sequence

但是,与早期版本不同的是,ES9 将无效的 unicode 序列解析为 undefined 并且不会抛出错误。 这在以下示例中显示

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)

上述代码输出结果如下

{parsed: undefined}
{parsed: "❤️"}

原始字符串

ES9 引入了一个特殊的属性 raw,可用于标记函数的第一个参数。 此属性允许我们在输入原始字符串时访问它们,而无需处理转义序列。

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)

上述代码输出结果如下

{Parsed: undefined, Raw: "\unicode"}
{Parsed: "❤️", Raw: "\u2764\uFE0F"}

正则表达式功能

在正则表达式中,点运算符或句点用于匹配单个字符。 这 . 点运算符跳过换行符,如 \n\r ,如下例所示

console.log(/Fql.Jiyik/.test('Fql_Jiyik')); //true
console.log(/Fql.Jiyik/.test('Fql\nJiyik')); //false
console.log(/Fql.Jiyik/.test('Fql\rJiyik')); //false

正则表达式模式表示为 /regular_expression/test() 方法接受一个字符串参数并搜索正则表达式模式。 在上面的示例中,test() 方法搜索以 Fql 开头的模式,后跟任何单个字符并以 Point 结尾。 如果我们在 Fql 和 Jiyik 之间的输入字符串中使用 \n 或 \r,则 test() 方法将返回 false。

true
false
false

ES9 引入了一个新标志 - DotAllFlag \s ,它可以与 Regex 一起使用来匹配行终止符和表情符号。 这在以下示例中显示

console.log(/Fql.Jiyik/s.test('Fql\nJiyik'));
console.log(/Fql.Jiyik/s.test('Fql\rJiyik'));

上述代码输出结果如下

true
true

命名捕获组

在 ES9 之前,捕获组是通过索引访问的。 ES9 允许我们为捕获组分配名称。 下面给出了相同的语法

(?<Name1>pattern1)

示例

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

查看笔记

扫码一下
查看教程更方便