7 Features of ES2022 You Should Know
Tags: javascript, webdev, whatsnew, es2022
Published: 2023-03-09 13:14:27

---
title: 7 Features of ES2022 You Should Know
published: true
date: 2023-03-09 11:00:00 UTC
tags: javascript, webdev, whatsnew, es2022
canonical_url: https://www.syncfusion.com/blogs/post/7-features-of-es2022.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddtbybjird9dq7kvo8hz.png
---
[JavaScript](https://en.wikipedia.org/wiki/JavaScript "Wikipedia page for JavaScript") is evolving continuously, and each year the latest edition of the [ECMAScript](https://en.wikipedia.org/wiki/ECMAScript "Wikipedia page for ECMAScript") specification is released with new features and changes. ES2022 is the 13th edition of JavaScript, released in June 2022.

As a developer, you should be up to date on these new features, as they help you improve the quality of your code. Let’s look at the most important features that reached the [fourth stage of the TC39 process](https://github.com/tc39/proposals/blob/HEAD/finished-proposals.md "TC39 process proposals on GitHub") and were published in the June 2022 release.

## 1. RegExp match indices

By using regular expressions, we can search for patterns in strings. **Regexp.exec** and **String.matchAll** are two methods used in JavaScript to retrieve a list of matches. Both return the matched substrings; the initial input string; the index in the input where the match was found; and the group’s object, consisting of substrings for any named capture groups. Refer to the following example.

```js
const animals = "Animals: Brown Bear, Koala, Polar Bear"
// without /d flag
const regex = /(Bear)/g
console.log(...animals.matchAll(regex))
// Output:
// [
// 'Bear',
// 'Bear',
// index: 15,
// input: "Animals: Brown Bear, Koala, Polar Bear",
// groups: undefined
// ] [
// 'Bear',
// 'Bear',
// index: 34,
// input: "Animals: Brown Bear, Koala, Polar Bear",
// groups: undefined
// ]
```

There may be situations where you need more than just the index of the match but also the start and end indices for each captured substring. With this new JavaScript feature, you can use the character **d** to express that you want both starting and ending indices of the specified matched string. Refer to the following example.

```js
const animals = "Animals: Brown Bear, Koala, Polar Bear"
// with /d flag
const regex2 = /(Bear)/dg
console.log(...animals.matchAll(regex2))
// Output:
// [
// 'Bear',
// 'Bear',
// index: 15,
// input: "Animals: Brown Bear, Koala, Polar Bear",
// groups: undefined,
// indices: [[15, 19], [15, 19], groups: undefined, length: 2 ]
// ] [
// 'Bear',
// 'Bear',
// index: 34,
// input: "Animals: Brown Bear, Koala, Polar Bear",
// groups: undefined,
// indices: [[34, 38], [34, 38], groups: undefined, length: 2 ]// ]
```

As you can see, when the new **/d** flag is used, it returns the start and end positions (indices) of each matched group capture.

## 2. Top-level await

Although the asynchronous functions have been used in JavaScript for some time now, before ES2022, **await** was only available in the scope of async. In ES2022, you can use **await** outside the context of an **async** method and provide a solution for the synchronization issues with which you have previously dealt. For example, **await** holds up the rendering of a module and its parents until the resources are imported and ensures that things are properly coordinated.

There are several use cases for top-level **await** :

- Allows modules to use runtime values to determine dependencies.
```js
// Appropriate translation keys are needed based on the language.
const translationKeys = await import(/api/${language} );

```

- Resource initialization.
```js
const connection = await dbConnector();
```

- Dependency fallbacks.
```js
let URL;
try {
  url = await import('https://cdn-a.com/jQuery');
} catch {
  url = await import('https://cdn-b.com/jQuery');
}
```

## 3. .at() for indexing

Before ES2022, square bracket notation was used to fetch a particular element in an array. This method is straightforward unless you need to perform a backward iteration, i.e., negative indexing. In the case of negative indexing, the common practice was to use **arr[arr.length — N]**, where array length is referred to and indexed from the end. Unfortunately, this method requires naming the indexable twice and adding an additional seven characters to the **.length**. It is also hostile to anonymous values; you need first to store the return value of a function in a temp variable to get the last item.

**arr.slice(-N)[0]** is another method that avoids the drawbacks of the **arr[arr.length — N]** method but also has its own performance drawbacks.

The **.at()** method introduced in ES2022 has simplified this process. In a case of positive indexing, **.at()** will work the same as the square brackets. But for negative indexing, the **.at()** method allows starting the iteration from the end.

```js
[a,b,c,d,e].at(3) //Output: d
[a,b,c,d,e].at(-2) //Output: d
```

Data types supported by **.at()** are string, array, and all typed array classes: Int8Array, Uint8Array, etc.

## 4. Accessible Object.prototype.hasOwnProperty

**Object.hasOwn()** is a static method that you can use to check if a property exists in an object or not. It returns **true** if the specified object contains the indicated property as its own, and if the property is inherited or doesn’t exist, it returns **false**. This method takes the object as the first argument and the property you want to check as the second.

**Object.hasOwn** is the intended alternative for the **Object.prototype.hasOwnProperty** method. Although **Object.prototype.hasOwnProperty** has been in JavaScript specification for quite a time, it has some drawbacks.

**\*\*hasOwnProperty\*\*** does not work for objects created using **Object.create(null)** as it does not inherit from **Object.prototype** , which makes the **hasOwnProperty** unreachable for the created object. Using **hasOwnProperty** , the object will throw an exception.

**hasOwnProperty()** can be overridden, as it is not a reserved JavaScript object method.

Due to these two raised problems, it is recommended to use **Object.hasOwn** over the **object.prototype.hasOwnProperty()**. Although it is possible to work around the mentioned issues by calling **hasOwnProperty()** on an external object, **hasOwn()** is more intuitive.

```js
const book = {
  name: "Harry Potter",
  author: "J.K. Rowling",
 }

// Using Object.prototype.hasOwnProperty() method
console.log(book.hasOwnProperty("name")) //Output: true
console.log(book.hasOwnProperty("price")) //Output: false

// Using Object.hasOwn method
console.log(Object.hasOwn(book, "name")) //Output: true

// Issues with hasOwnProperty

// Issue 01: Doesn't work for objects created using Object.create(null)const person = Object.create(null)
person.name = "Mike"console.log(person.hasOwnProperty("name")) //Output: TypeError: object2.hasOwnProperty is not a function
console.log(Object.hasOwn(person, "name")) //Output: true
  
// Issue 02: hasOwnProperty can be overridden
const author = {
  name: "J.K. Rowling",
  hasOwnProperty() {
    return false
  },
}  

console.log(author.hasOwnProperty("name")) //Output: false
console.log(Object.hasOwn(author, "hasOwnProperty")) //Output: true

```

## 5. Error cause

Errors are raised to identify runtime abnormalities. However, if the error is thrown from a deep internal method, identifying the reason behind it may not be straightforward without a proper exception design pattern.

The **.cause** property of the error object allows you to specify the reason behind the unexpected exceptions. This is a perfect way to chain the errors together and is very helpful in deeply nested functions, as the errors can be chained without using over-elaborated formalities on wrapping the errors in conditions.

```js
try {  
  const result = 2 / 0;  
  console.log(result);
} catch (error) {  
    console.err(error);  
    throw new Error('Something went wrong', { cause: error });
  }
```
## 6. Class

**Public and private instance fields**

```js
class User {
  constructor(){
      Public fieldthis.userName = 'Hermione Granger'
      Private fieldthis._password = 'abc123';
  }
}

const user = new User();
console.log(user.userName); // Hermione Granger - public fields are accessible outside the class

console.log(user._password); // abc123 - no error thrown, can access the private field from outside the class
```

Refer to the previous example. As you can see, before ES2022, you had to invoke the constructor to define both public and private fields. Moreover, although the **Private** keyword was used to declare the field as private, when we try to access it outside the class, it doesn’t throw any errors. This is because **private** is only a naming convention used to define **private fields** and not exactly something that JavaScript itself enforces.

With ES2022, you don’t have to define fields inside a constructor anymore. Also, you can define a private field by inserting **#** as a prefix of the field name. This avoids accessing private fields outside the class and throws an error if you try to do so.

```js
class User {
  userName = 'Hermione Granger'
  #password = 'abc123';
}

const user = new User();
console.log(user.userName); // Hermione Granger - public fields are accessible outside the class

console.log(user.#password); // Uncaught SyntaxError: Private field '#password' must be declared in an enclosing class
```

### Static class fields and private static methods

Before ES2022, static fields and methods could not be accessed in an instance of a class, only in the prototype, like in the following code.

```js
class User {
  ...
}

User.userName = "Hermione Granger";
```

This feature of ES2022 lets you define them directly inside the class body using the keyword **static**.

```js
class User {
  static userName = "Hermione Granger"
}

User.userName;
```

Similarly, you can combine the static keyword with **#** to create a private static method that is only accessible from inside the prototype class. 

```js
class User {
  #userName;
  
  static #login() {this.#userName = "Hermione Granger";
}

User.#login() // Returns an error
```

## 7. Ergonomic brand checks for private fields

If you try to access a private field of an object that has not been declared, it will throw an exception and not an undefined error like it usually does with public fields.

You can use a **try/catch** inside the class to check if a private field exists, like in the next example.

```js
class UserLogin {
   
   // Initialized as null#userName = null;
    
    get #getUser(){if(!this.#userName){throw new Error('No Data!');
      } 
      return this.#userName
    }
    
    static isLogin(user){
        try {
            obj.#getUser;return true;
        } catch {
            return false; 
        }
    }
}
```

The issue is that you don’t know whether the **catch** block is executed because the getter is not present or because it threw an error.

The latest **\*\*in\*\*** operator introduced in ES2022 provides an easy way to overcome this issue. By using it, you will be able to check whether a field is present in a specific class or not. Let’s adjust our previous example.

```js
class UserLogin {
   // Initialized as null#userName = null;
    get #getUser(){if(!this.#userName){throw new Error('No Data!');
        }
        return this.#userName;
    }
    
    static isLogin(user){
        return #userName in user && #getUser in user
    }
}

```

The **isLogin** will check the presence of private fields in the class.

## Conclusion

In this article, I discussed the latest ES2022 JavaScript features that would help you to improve your coding skills. I hope you will use these new features during your development process to make your code more updated.

I hope you have found this article helpful. Thank you for reading!

The Syncfusion [JavaScript](https://www.syncfusion.com/javascript-ui-controls "JavaScript UI controls") suite is the only suite you will ever need to build an application. It contains over 65 high-performance, lightweight, modular, and responsive UI components in a single package. Download the [free trial](https://www.syncfusion.com/downloads/essential-js2 "Free evaluation of the Essential Studio") and evaluate the controls today.

If you have any questions or comments, you can contact us through our [support forums](https://www.syncfusion.com/forums "Syncfusion Support Forums"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal.](https://www.syncfusion.com/feedback/ "Syncfusion Feedback Portal") We are always happy to assist you!

## Related blogs

- [5 Best Practices in Handling HTTP Errors in JavaScript](https://www.syncfusion.com/blogs/post/handling-http-errors-javascript.aspx "Blog: 5 Best Practices in Handling HTTP Errors in JavaScript")
- [10 Tips and Tricks to Handle JavaScript Objects](https://www.syncfusion.com/blogs/post/10-tips-and-tricks-to-handle-javascript-objects.aspx "Blog: 10 Tips and Tricks to Handle JavaScript Objects")
- [Null vs. Undefined in JavaScript](https://www.syncfusion.com/blogs/post/null-vs-undefined-in-javascript.aspx "Blog: Null vs. Undefined in JavaScript")
- [JavaScript Debounce vs. Throttle](https://www.syncfusion.com/blogs/post/javascript-debounce-vs-throttle.aspx "Blog: JavaScript Debounce vs. Throttle")