JavaScript is the most commonly used programming language, according to Stack Overflow’s 2020 Developer Survey, and it is continually evolving. In fact, new ECMAScript specifications have been released every year since 2015. At the time of this writing, several new feature proposals have passed the fourth proposal stage and are anticipated to be included in ES2022, JavaScript’s 13th version.
In this article, we’ll take a look at the eight feature proposals that are expected to be released in mid-2022:
await
for delaying execution of modulesRegExp
match indicesclass
field declarationsObject.prototype.hasOwnProperty
static{}
blocks for initialization during class definitioncause
property for chaining errorsawait
ES2022 will enable developers to use await
outside of the asynchronous (async
) function scope, making it easier to use at the module level.
Here’s an example of how await
is used prior to ES2022:
import users from './users' const getUsers = async() => { let users = await users() return users }
Here’s the same example, showing how await
will be used under ES2022:
let users = await import './users'
The top-level await
feature delays the execution of current and parent modules until the imported module is loaded. Using this feature, modules can use runtime values to determine dependencies. Top-level await
can also be used as a fallback for dependencies.
let users; try { users = await import('https://example1.com/users'); } catch { users = await import('https://example2.com/users'); }
RegExp
match indices with the d
flagRegular expression matches are patterns that are used to find certain character combinations in strings. In a result, RegExp.exec
and String.matchAll
return a list of matches.
const names = 'Names: John, Frank, Johnson, Kelly' const regex = /(John)/g; // .exec // RegExp(regex).exec(names); // [ // 'John', // index: 7, // input: 'Names: John, Frank, Johnson, Kelly', // groups: undefined // ] // matchAll const matches = [...names.matchAll(regex)]; matches[0]; // [ // 'John', // 'John', // index: 7, // input: 'Names: John, Frank, Johnson, Kelly', // groups: undefined // ]
RegExp.exec
delivers results individually, while String.matchAll
returns an iterator that may be used to iterate over all matches.
ES2022 will allow developers to use the d
flag to specify the starting and ending indices of matches
in a RegExp
result. Here’s an example:
const names = 'Names: John, Frank, Johnson, Kelly' const regex = /(John)/gd; const matches = [...names.matchAll(regex)]; matches[0]; // [ // "John", // "John", // groups: undefined // index: 7 // indices:[] // [7, 11], // [7, 11] // ] // groups: undefined
class
field declarations#
prefixPrior to ES2022, class fields are simply defined in the constructor
. Fields prefixed by an underscore (_
) are traditionally inaccessible outside of the class since they are considered private. Take a look at the following sample code:
class User { constructor(){ // public field this.name = 'kodex' // private field this._password = '1234'; } } const user = new User(); console.log(user.name); // name - public fields are accessible outside the classes user._password = 'qwert'; console.log(user._password); // password - no error thrown, we can access it from outside the class
In this example, the private _password
property is accessed and modified outside of the class.
ES2022 will enable developers to define and enforce a private field by simply inserting a #
prefix before the field name. ES2022 also removes the need for public or private fields to be defined in the constructor()
.
Consider the following example:
class User { // public field name = 'kodex' // private field #password = '1234'; } const user = new User() console.log(user.#password); user.#password = 'qwert'; // error - Private field '#password' must be declared in an enclosing class
In this code, an attempt to access the private field outside of the class results in an error.
#
prefixES2022 also enables developers to use the #
prefix with private methods and accessors (“getters” and “setters”) to restrict a class’s methods and variables. This keeps the methods and accessors strictly internal and prevents them from being accessed outside of the class. Here’s an example:
class User { // public field name = 'kodex' // private field #password = '1234'; #getPwd(){ return this.#password } set #setPwd(data){ this.#password = data } } const user = new User() // Error - Private field '#getPwd' must be declared in an enclosing class console.log(user.#getPwd); // Error - Private field '#setPwd' must be declared in an enclosing class user.#setPwd = 'qwert';```
static
keywordStatic class
fields and methods are only accessible in the class prototype, rather than in every instance of the class. Prior to ES2022, a class
‘s static fields may be specified as follows:
class Animal {} Animal.cow = "mammal"
Under ES2022, the static
keyword may be used to specify a class
‘s static fields and private static methods. Here’s an example:
class Animal { static cow = "mammal" }
in
keywordAn attempt to access a private field outside of a class currently results in an exception being thrown, rather than undefined
being returned. We could use try
/catch
inside of a class to determine if a private field exists. However, the issue with this method is that it can be difficult to determine the source of an exception.
ES2022 will provide developers with the in
keyword that can be used to produce a Boolean indicating the presence of a private field. This simple solution does not require a try
/catch
method or exceptions:
class Person{ #name = 'Kelly'; get #getName(){ return #name; } set #setName(){ #name = 'Anna'; } static hasTitle(obj){ return #name in obj; } }
.at()
methodThe .at()
method provides easy access to any index of an array or string, either positive or negative. Here’s an example:
array= [1, 2, 3, 4, 5] console.log(array[array.length-1]); // 5 console.log(array.at(-1)); // 5
ES2022 will enable developers to add the .at()
method to an array and use a negative integer value to count backward from the end of the array.
Object.prototype.hasOwnProperty
with the Object.hasOwn()
methodBy convention, the hasOwnProperty
can’t be used outside of the prototype itself. An object could have a property called hasOwnProperty
that differs from the Object.prototype.hasOwnProperty
. Here’s an example:
const employee = { hasOwnProperty:()=> { return false } } obj.hasOwnProperty('prop'); // false
ES2022 will enable developers to address this issue, by using the Object.hasOwn()
method. This method takes the object as the first parameter and the property we wish to verify as the second parameter:
const employee = { name: 'Grace', age: 18 } Object.hasOwn(employee, 'name'); // true Object.hasOwn(employee, 'position'); // false
static{}
blocksTraditionally, statements like try
/catch
are evaluated outside of the class body during initialization.
class UserStatus{ status = false; get getStatus(){ if(!this.#status){ throw new Error('User is not active'); } return this.#status } } // evaluate outside the class body try { const state = UserStatus.getStatus; UserStatus.status = state } catch { UserStatus.status = false }
ES2022 will permit developers to use static{}
blocks to evaluate statements within the scope of a class declaration. This is useful in instances in which there is a need to set up multiple static fields. static{}
blocks permit access to a class’s private states (methods and fields) and allow information to be shared between classes or functions declared in the same scope.
let initState; class UserStatus{ #status = false; get getStatus(){ if(!this.#status){ throw new Error('User is not active'); } return this.#status } static { initState = () => { this.#status = this.getStatus; } } } initState();
cause
propertyErrors are traditionally identified and addressed during runtime using contextual information such as error messages and error instance properties. If an error occurs in a deeply nested function, its cause can be difficult to determine in the absence of a proper exception design pattern.
function processData(arrayData) { return arrayData.map(data => { try { const json = JSON.parse(data); return json; } catch (error) { // throw random error } });
In ES2022, the cause
property is added to the Error()
constructor as an extra parameter, allowing errors to be chained without the need for unnecessary formalities on wrapping the errors in conditions.
function processData(arrayData) { return arrayData.map(data => { try { const json = JSON.parse(data); return json; } catch (err) { throw new Error( `Data processing failed`, {cause: err} ); } }); }
It is essential that developers stay current with the latest language specifications. In this article, we looked at eight new features that will be available with JavaScript’s ES2022 specification. JavaScript is continually evolving, with new features being added each year. We’re excited to see what new features are in store for ES2023!
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowconsole.time is not a function
errorExplore the two variants of the `console.time is not a function` error, their possible causes, and how to debug.
jQuery 4 proves that jQuery’s time is over for web developers. Here are some ways to avoid jQuery and decrease your web bundle size.
See how to implement a single and multilevel dropdown menu in your React project to make your nav bars more dynamic and user-friendly.
NAPI-RS is a great module-building tool for image resizing, cryptography, and more. Learn how to use it with Rust and Node.js.