ES9 - New Features


Advertisements

Here, we will learn about the new features in ES9. Let us begin by understanding about the asynchronous generators.

Asynchronous Generators and Iteration

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
}

Example

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}

for await of loop

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.

  • iterable − Object whose iterable properties are to be iterated over.
for await (variable of iterable) {
   statement
}

Example

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

Example

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

Rest/Spread Properties

ES9 supports the use of Rest and Spread operators with Objects.

Example: Object and Rest Operator

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}

Example: Object and Spread operator

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}

Promise: finally()

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.

Syntax

The below mentioned syntax is for the function finally().

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

Example

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

Template Literal revision

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: "❤️"}

Raw Strings

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.

Example

<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"}

Regular Expression feature

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

Named Capture Groups

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)

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

The output of the above code is as shown below −

1999
04
Advertisements