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:
- Top-level
await
for delaying execution of modules RegExp
match indicesclass
field declarations- Ergonomic brand checks for private fields
- Negative indexing of an array or string
- More accessible
Object.prototype.hasOwnProperty
static{}
blocks for initialization during class definitioncause
property for chaining errors
Delaying the execution of modules with top-level await
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
flag
Regular 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
Defining and enforcing private fields with the #
prefix
Prior 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.
Restricting private field methods and accessors with the #
prefix
ES2022 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';```
Specifying static fields and private static methods with the static
keyword
Static 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" }
Ergonomic brand checks for private fields using the in
keyword
An 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; } }
Negative indexing with the .at()
method
The .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.
More accessible Object.prototype.hasOwnProperty
with the Object.hasOwn()
method
By 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
Initialization during class definition evaluation with static{}
blocks
Traditionally, 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();
Chaining errors with the cause
property
Errors 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} ); } }); }
Conclusion
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!
The post What to expect from ES2022 appeared first on LogRocket Blog.
from LogRocket Blog https://ift.tt/ZrXW13h
via Read more