JavaScript is one of the most popular programming languages. One of the reasons for its popularity is its evolution over time. JS is getting better with time and new features are getting to it added regularly. A new specification version of the programming language is being released every year since 2015. This year, the 13th edition of the JavaScript standard, ECMAScript 2022 will be released. ****Some new features and improvements are getting added to the JavaScript with the release of the ES2022. So here, we'll look at some of the new features and will try to understand them with examples.
1. Top-level await
Asynchronous functions were added to JavaScript in 2017. Until now, we could only use await inside the async
functions. But now, the await
keyword can also be used outside the async
functions at the top level of a module to wait for a Promise
.
So, while using top-level await
in a module where one module imports another one, the execution of the parent module will only start when the execution of the child module code is finished.
Let's have a look at the example to have a better understanding of the feature.
Before ES2022
await Promise.resolve(console.log("Inkoop"))
// SyntaxError: await is only valid in async function
const print = async () => {
await Promise.resolve(console.log("Inkoop"))
}
print() // Output: Inkoop
After ES2022
await Promise.resolve(console.log("Inkoop")) // Inkoop
2. Private Class Fields and Methods
By default, class
fields and methods are public in JavaScript, which means these fields and methods are accessible globally and can be read or modified from outside of the class
. Earlier, developers used to prefix class
fields with an underscore _
to mark them private. These fields were hidden by convention only. There's nothing which prevents accessing those fields. The JavaScript specification does not give any particular meaning to the fields prefixed with an underscore either.
But now, making class
fields or methods private is as simple as prefixing them with a hash #
. Unlike the underscore convention, fields and methods which start with #
are made private by the JavaScript specification itself. These private fields and methods are only accessible inside the class in which they are declared. Trying to access these fields from outside of the class will throw an error.
class MyClass {
#firstName = "Lorem"
lastName = "Ipsum"
printPrivateField() {
console.log(this.#firstName)
}
#sayBye() {
console.log("Bye")
}
}
const instance = new MyClass()
console.log(instance.#firstName) // SyntaxError: Private field '#firstName' must be declared in an enclosing class
console.log(instance.lastName) // Ipsum
instance.printPrivateField() // Lorem
instance.#sayBye() // SyntaxError: Private field '#sayBye' must be declared in an enclosing class
3. at()
method for Strings
, Arrays
, and TypedArrays
So far, we've been using square brackets []
to access the elements of an array. In bracket notation syntax, we just need to pass the index of the element which we want to access inside the square brackets and it returns the item at that particular index. But, to access the elements of an array backwards, we need to use the length property of the array.
Up to this point, we couldn't use negative indexing to get the elements of an array backwards like other languages as JavaScript didn't allow negative indexing. Unfortunately, JavaScript's language design makes it impossible to use negative indexing with bracket notation as bracket notation syntax isn't specific to arrays and strings only, it also applies to objects.
So, ES2022 introduces a new method to Array
, String
, and TypedArray
. The at
method is almost similar to the bracket notation as it also takes an integer and returns the item at that index. But, it also supports negative indexing. So now, we can access the elements of an array
or a string
backwards using the at
method with negative indexing.
const array = ["inkoop", "draxlr", "sup"]
// Using the length property
const lastItem = array[array.length - 1]
console.log(lastItem) // Output: sup
// Using the new at method
const lastElement = array.at(-1)
console.log(lastElement) // Output: sup
console.log(array.at(-2)) // Output: draxlr
console.log(array.at(0)) // Output: inkoop
4. Object.hasOwn
Method
To check if a property exists in an object or not, now we can use Object.hasOwn
method which is a convenient alternative to Object.prototype.hasOwnProperty
method. Both of these methods return a boolean
which indicates whether the object has the specified property as its own property or not. Object.prototype.hasOwnProperty
has been there in JavaScript specification for quite a time now but it had some drawbacks. hasOwnProperty
isn't a reserved JavaScript object method and can be overridden. It has one more issue if an object is created using Object.create(null)
, it does not inherit from Object.prototype
which makes the hasOwnProperty
unreachable for the created object. Using hasOwnProperty
on the object will throw an error.
To overcome these issues, the Object.hasOwn
method has been introduced in ES2022. It takes The JavaScript object instance as the first parameter and the name of the property as its second parameter. The method returns true
if the specified property exists in the specified object itself, otherwise, it'll return false
.
So now, it's better to use Object.hasOwn
method instead of the Object.prototype.hasOwnProperty
method if the environment supports the newer one.
const object = {
name: "Draxlr",
}
console.log(object.hasOwnProperty("name")) // Output: true
console.log(object.hasOwnProperty("hasOwnProperty")) // Output: false
// issue with hasOwnProperty
const object2 = Object.create(null)
object2.name = "lorem"
console.log(object2.hasOwnProperty("name")) // TypeError: object2.hasOwnProperty is not a function
// using Object.hasOwn method
console.log(Object.hasOwn(object2, "name")) // Output: true
// another issue
const object3 = {
name: "JavaScript",
hasOwnProperty() {
return false
},
}
console.log(object3.hasOwnProperty("name")) // Output: false
// using Object.hasOwn method
console.log(Object.hasOwn(object3, "name")) // Output: true
console.log(Object.hasOwn(object3, "hasOwnProperty")) // Output: true
5. RegExp
match indices
ES2022 adds a new feature to Regular Expressions called Match indices. With the help of this feature, we can get extra information about the start and end indices of the captured substring. To get this additional information, we just need to pass the/d
flag in the regular expression. This feature adds indices property to the result array returned by RegExp.prototype.exec
and String.prototype.matchAll
methods. The indices property is an array which contains the start and end indices of each matched substring relative to the starting of the input.
Let's understand it better with an example.
const str = "next time there won't be a next time."
// without /d flag
const regex = /(next)/g
console.log(...str.matchAll(regex))
// Output:
// [
// 'next',
// 'next',
// index: 0,
// input: "next time there won't be a next time.",
// groups: undefined
// ] [
// 'next',
// 'next',
// index: 27,
// input: "next time there won't be a next time.",
// groups: undefined
// ]
// with /d flag
const regex2 = /(next)/dg
console.log(...str.matchAll(regex2))
// Output:
// [
// 'next',
// 'next',
// index: 0,
// input: "next time there won't be a next time.",
// groups: undefined,
// indices: [ [ 0, 4 ], [ 0, 4 ], groups: undefined ]
// ] [
// 'next',
// 'next',
// index: 27,
// input: "next time there won't be a next time.",
// groups: undefined,
// indices: [ [ 27, 31 ], [ 27, 31 ], groups: undefined ]
// ]
6. Ergonomic brand checks for Private Fields
As mentioned earlier in the blog, ES13 adds private class fields feature to JavaScript but what if we want to check if a private field exists in the class
or not. Private fields have a built-in brand check, so accessing a non-existent private field on a class
throws an exception. Meanwhile, trying to access a non-existent public field returns undefined
.
Using try/catch
to handle the exception will work in some cases, but won't that be awkward. Don’t worry as ES13 also comes up with a better syntax to check for a private field in a class
. We can simply use the in
operator to check whether a private field or method exists in a class or not. The in
operator returns true
if the specified private field or method has been declared, otherwise false
.
class User {
#name = "Random User"
static isNamePresent(object) {
console.log(#name in object)
}
}
const instance = new User()
User.isNamePresent(instance) // Output: true
User.isNamePresent({}) // Output: false
Hope you found this blog helpful and got to learn something new. All of the above-listed features are now available in most of the browsers. So, you can also go and check out these features.