Skip to content

Latest commit

 

History

History
202 lines (147 loc) · 5.51 KB

ES2022.MD

File metadata and controls

202 lines (147 loc) · 5.51 KB

ES2022 - ES13

See the ES2022 standard for full specification of the ECMAScript 13 language.

ES13 includes the following new feature proposals:

ECMAScript 13 Features

Top-level await

In old behavior, When the async/await feature was first introduced, attempting to use an await outside of an async function resulted in a SyntaxError. Many developers utilized as an alternative IIFE (Immediately Invoked Function Expression) as a way to get access to the feature.

Example:

await Promise.resolve(console.log('Hello World'));
// Output: SyntaxError: await is only valid in async function

// Alternative to fix the problem
(async function() {
  await Promise.resolve(console.log('Hello World'));
  // Output: Hello World
}());

In new behavior, With top-level await, we don't need to use more life hacks.

await Promise.resolve(console.log('Hello World'));
// → Hello World

Use Cases

// 1. Dynamic dependency pathing

const strings = await import(`/i18n/${navigator.language}`);

// This allows for Modules to use runtime values in order to determine dependencies. 
// This is useful for things like development/production splits, internationalization, environment splits, etc.


// 2. Resource initialization

const connection = await dbConnector();

// This allows Modules to represent resources and also to produce errors in cases where the Module will never be able to be used.


// 3. Dependency fallbacks

let jQuery;
try {
  jQuery = await import('https://cdn-a.com/jQuery');
} catch {
  jQuery = await import('https://cdn-b.com/jQuery');
}

Static class fields and methods

Static class fields and methods are not used on instances of a class. Instead, can be called on the class itself and is declared using the static keyword.

Static methods are often utility functions, and helpers, whereas static properties are useful for caches, fixed-configuration, or any other data we don’t need to be replicated across instances.

Example:

// Static class fields
class Test {
  static firstName = 'test-static-name';
}

Test.firstName

// Output: test-static-name


// Static class methods
class Test {
  static greeting(){
    console.log('Hello this is a greeting from a static method');
  }
}

Test.greeting();

// Output: Hello this is a greeting from a static method

Static class initialization blocks

This new feature provides a mechanism for additional static initialization during class definition evaluation.

Example:

class Test {
  static numbers = [1,2,3,4,5,6];
  static evenNumbers = [];
  static oddNumbers = [];

  // static class initialization block
  static {
   this.numbers.forEach((number) => {
     if(!(number % 2) ) {
       this.evenNumbers.push(number);
     } else {
        this.oddNumbers.push(number);
     }
   });
  }
}

Test.evenNumbers;
// Output: [2, 4, 6]

Test.oddNumbers;
// Output: [1, 3, 5]

Error.cause

Error and its subclasses now let us specify the reason behind the error. Sometimes, we catch errors that are thrown during more deeply nested function calls and would like to attach more information to them. With the Error cause, we can add more intrinsic information for our errors. To use this new feature, we should specify the error options as a second parameter, and with the cause key we can pass the error that we want to chain.

Example:

const getUsers = async(array)=> {
  try {
    const users =  await fetch('https://myapi/myusersfake');
    return users;
  } catch (error) {
    console.log('enter')
    throw new Error('Something when wrong, please try again later', { cause: error })
  }
}

try{
  const users = await getUsers();
} catch(error) {
  console.log(error); // Error: The array need a minimum of two elements
  console.log(error.cause); // TypeError: Failed to fetch
}

.at()

Until this point, programmers have asked for the ability to do negative indexing of JS Arrays, as you can do with other programming languages. That is, asking for the ability to write arr[-1] instead of arr[arr.length-1], where negative numbers count backward from the last element.

.at() helps with the negative indexing, the .at() method that is supported by Array, String, or TypedArray.

Example:

// The old behavior
const fruitsArray = ['banana', 'apple', 'orange', 'kiwi'];
console.log(fruitsArray[fruitsArray.length -1])
// Output: kiwi

const fruit = 'kiwi';
console.log(fruit[fruit.length -1])
// Output: i


// The new behavior
const fruitsArray = ['banana', 'apple', 'orange', 'kiwi'];
console.log(fruitsArray.at(-1))
// Output: kiwi
console.log(fruitsArray.at(1))
// Output: apple

const fruit = 'kiwi';
console.log(fruit.at(-1))
// Output: i

Object: .hasOwn()

Today, it is very common (especially in library code) to write code like

let hasOwnProperty = Object.prototype.hasOwnProperty

if (hasOwnProperty.call(object, "foo")) {
  console.log("has property foo")
}

This new feature simplifies that code to

if (Object.hasOwn(object, "foo")) {
  console.log("has property foo")
}