Here, we will learn about the new features in ES9. Let us begin by understanding about the asynchronous generators.
Asynchronous generators can be made asynchronous by using the async keyword. The syntax for defining an async generator is given below −
async function* generator_name() { //statements }
Following example shows an async generator which returns Promise on each call to the next() method of generator.
<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>
The output of the above code will be as follows −
{value: 1, done: false} {value: 2, done: false} {value: 3, done: false} {value: undefined, done: true}
Asynchronous iterables cannot be iterated using the traditional for..of loop syntax as they return promises. ES9 introduces the for await of loop to support asynchronous iteration.
The syntax for using the for await of loop is given below, where,
On each iteration a value of a different property is assigned to variable and a variable may be declared with const, let, or var.
for await (variable of iterable) { statement }
The following example shows the use of for await of loop to iterate an async generator.
<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>
The output of the above code will be as shown below −
end of script 1 2 3
The following example iterates an array using the for await of loop.
<script> async function fntest(){ for await (const val of [10,20,30,40]){ console.log(val) } } fntest(); console.log('end of script') </script>
The output of the above code will be as follows −
end of script 10 20 30 40
ES9 supports the use of Rest and Spread operators with Objects.
The following example shows the use of rest operator with an object. The value of age property of student is copied into the age variable while the values of the remaining properties are copied into the other variable using the rest syntax `...`.
<script> const student = { age:10, height:5, weight:50 } const {age,...other} = student; console.log(age) console.log(other) </script>
The output of the above code will be as given below −
10 {height: 5, weight: 50}
The spread operator can be used to combine multiple objects or cloning objects. This is shown in the following example −
<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>
The output of the above code will be as stated below −
{a: 10, b: 20} {a: 10, b: 20, c: 30}
The finally() is executed whenever a promise is settled, regardless of its outcome. This function returns a promise. It can be used to avoid code duplication in both the promise's then() and catch() handlers.
The below mentioned syntax is for the function finally().
promise.finally(function() { }); promise.finally(()=> { });
The following example declares a async function that returns the square of a positive number after a delay of 3 seconds. The function throws an error if a negative number is passed. The statements in the finally block is executed in either case, whether the promise is rejected or resolved.
<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>
The output of the above code will be as shown below
Start End //after 3 seconds result is 100 inside finally executes all the time
As of ES7, tagged templates conform to the rules of the following escape sequences −
Unicode escape sequences are represented using "\u", for example \u2764\uFE0F
Unicode code point escape sequences are represented using "\u{}", for example \u{2F}
Hexadecimal escape sequences are represented using "\x", for example \xA8
Octal literal escape sequences are represented using "" and followed by one or more digits, for example \125
In ES2016 and earlier, if invalid escape sequences are used with tagged functions a Syntax Error will be thrown as shown below −
//tagged function with an invalid unicode sequence myTagFn`\unicode1` // SyntaxError: malformed Unicode character escape sequence
However, unlike the earlier versions, ES9 parses the invalid unicode sequence to undefined and does not throw an error. This is shown in the following example −
<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>
The output of the above code will be as shown below −
{parsed: undefined} {parsed: "❤️"}
ES9 introduces a special property raw, available on the first argument to the tag function. This property allows you to access the raw strings as they were entered, without processing the escape sequences.
<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>
The output of the above code will be as follows −
{Parsed: undefined, Raw: "\unicode"} {Parsed: "❤️", Raw: "\u2764\uFE0F"}
In regular expressions, the dot operator or a period is use to match a single character. The . dot operator skips line break characters like \n, \r as shown in the below example −
console.log(/Tutorials.Point/.test('Tutorials_Point')); //true console.log(/Tutorials.Point/.test('Tutorials\nPoint')); //false console.log(/Tutorials.Point/.test('Tutorials\rPoint')); //false
A regular expression pattern is represented as the / regular_expression /. The test() method takes a string parameter and searches for the regex pattern. In the above example, the test() method searches for pattern starting with Tutorials, followed by any single character and ending with Point. If we use the \n or \r in the input string between Tutorials and Point the test() method will return false.
true false false
ES9 introduces a new flag - DotAllFlag (\s) that can be used with Regex to match line terminators and emojis. This is shown in the following example −
console.log(/Tutorials.Point/s.test('Tutorials\nPoint')); console.log(/Tutorials.Point/s.test('Tutorials\rPoint'));
The output of the above code will be as mentioned below −
true true
Prior to ES9, capture groups were accessed by indexes. ES9 allows us to assign names to capture groups. The syntax for the same is given below −
(?<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);
The output of the above code is as shown below −
1999 04