The Latest ECMA Script 2022 (ES13) JavaScript Released !
The Latest ES13 JavaScript Features
ECMAScript 2022 (ES13) is a new JavaScript standard set to be released in June 2022. Let’s go through an overview of the last few changes that are to be in the new release as they finished proposals (those that have reached Stage 4 in the proposal process and thus are implemented in several implementations and will be in the next practical revision).
ECMAScript 2022 features nine finished proposals:
- Class field declarations
- Ergonomic brand checks for private fields
- Await operator at the top-level
- Class Static Block
- Regexp Match Indices
- Method .at() function for Indexing
- Accessible Object.prototype.hasOwnProperty()
- Error Cause
- Array find from last
1. Class Field Declarations
Before ES13, class fields could only be declared in the constructor. Unlike in many other languages, we could not declare or define them in the outermost scope of the class.
class Car {
constructor() {
this.color = 'blue';
this.age = 2;
}
}
const car = new Car();
console.log(car.color); // blue
console.log(car.age); // 2
ES13 removes this limitation. Now we can write code like this:
class Car {
color = 'blue';
age = 2;
}
const car = new Car();
console.log(car.color); // blue
console.log(car.age); // 22. Ergonomic Brand Checks for Private Fields
We can use this new feature to check if an object has a particular private field in it, using the
inoperator.class Car { #color; hasColor() { return #color in this; } } const car = new Car(); console.log(car.hasColor()); // true;The
inoperator is able to correctly distinguish private fields with the same names from different classes:class Car { #color; hasColor() { return #color in this; } } class House { #color; hasColor() { return #color in this; } } const car = new Car(); const house = new House(); console.log(car.hasColor()); // true; console.log(car.hasColor.call(house)); // false console.log(house.hasColor()); // true console.log(house.hasColor.call(car)); // false
3. Await Operator at the Top Level
In JavaScript, the
awaitoperator is used to pause execution until aPromiseis settled (fulfilled or rejected).Previously, we could only use this operator in an
asyncfunction – a function declared with theasynckeyword. We could not do so in the global scope.
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
// SyntaxError: await is only valid in async functions
await setTimeoutAsync(3000);
With ES13, now we can:
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
// Waits for timeout - no error thrown await setTimeoutAsync(3000); 4. Class static Block
ES13 allows the definition of
staticblocks that will be executed only once, at the creation of the class. This is similar to static constructors in other languages with support for object-oriented programming, like C# and Java.A class can have any number of
static {}initialization blocks in its class body. They will be executed, along with any interleaved static field initializers, in the order they are declared. We can use thesuperproperty in astaticblock to access properties of the super class.
class Vehicle {
static defaultColor = 'blue';
}
class Car extends Vehicle {
static colors = [];
static {
this.colors.push(super.defaultColor, 'red');
}
static {
this.colors.push('green');
}
}
console.log(Car.colors); // [ 'blue', 'red', 'green' ]5. RegExp Match Indices
This new feature allows us to specify that we want the get both the starting and ending indices of the matches of a
RegExpobject in a given string.Previously, we could only get the starting index of a regex match in a string.
const str = 'sun and moon'; const regex = /and/; const matchObj = regex.exec(str); // [ 'and', index: 4, input: 'sun and moon', groups: undefined ] console.log(matchObj);We can now specify a
dregex flag to get the two indices where the match starts and ends.const str = 'sun and moon'; const regex = /and/d; const matchObj = regex.exec(str); /** [ 'and', index: 4, input: 'sun and moon', groups: undefined, indices: [ [ 4, 7 ], groups: undefined ] ] */ console.log(matchObj);With the
dflag set, the object returned will have anindicesproperty that contains the starting and ending indices.
6. at() Method for Indexing
We typically use square brackets (
[]) in JavaScript to access theNth element of an array, which is usually a simple process. We just access theN - 1property of the array.
const arr = ['a', 'b', 'c', 'd'];
console.log(arr[1]); // b
However, we have to use an index of
arr.length - Nif we want to access theNth item from the end of the array with square brackets.
const arr = ['a', 'b', 'c', 'd'];
// 1st element from the end
console.log(arr[arr.length - 1]); // d
// 2nd element from the end
console.log(arr[arr.length - 2]); // c
The new
at()method lets us do this in a more concise and expressive way. To access theNth element from the end of the array, we simply pass a negative value of-Ntoat().
const arr = ['a', 'b', 'c', 'd'];
// 1st element from the end
console.log(arr.at(-1)); // d
// 2nd element from the end
console.log(arr.at(-2)); // c
Apart from arrays, strings and
TypedArrayobjects also now haveat()methods.
const str = 'Coding Beauty';
console.log(str.at(-1)); // y
console.log(str.at(-2)); // t
const typedArray = new Uint8Array([16, 32, 48, 64]);
console.log(typedArray.at(-1)); // 64
console.log(typedArray.at(-2)); // 48 7. Object.prototype.hasOwnProperty() Method
In JavaScript, we can use the
Object.prototype.hasOwnProperty()method to check if an object has a given property.class Car { color = 'green'; age = 2; } const car = new Car(); console.log(car.hasOwnProperty('age')); // true console.log(car.hasOwnProperty('name')); // falseBut there are certain problems with this approach. For one, the
Object.prototype.hasOwnProperty()method is not protected – it can be overridden by defining a customhasOwnProperty()method for a class, which could have completely different behavior fromObject.prototype.hasOwnProperty().class Car { color = 'green'; age = 2; // This method does not tell us whether an object of // this class has a given property. hasOwnProperty() { return false; } } const car = new Car(); console.log(car.hasOwnProperty('age')); // false console.log(car.hasOwnProperty('name')); // falseAnother issue is that for objects created with a
nullprototype (usingObject.create(null)), trying to call this method on them will cause an error.const obj = Object.create(null); obj.color = 'green'; obj.age = 2; // TypeError: obj.hasOwnProperty is not a function console.log(obj.hasOwnProperty('color'));One way to solve these issues is to use to call the
call()method on theObject.prototype.hasOwnPropertyFunctionproperty, like this:const obj = Object.create(null); obj.color = 'green'; obj.age = 2; obj.hasOwnProperty = () => false; console.log(Object.prototype.hasOwnProperty.call(obj, 'color')); // true console.log(Object.prototype.hasOwnProperty.call(obj, 'name')); // falseThis isn’t very convenient. We can write our own reusable function to avoid repeating ourselves:
function objHasOwnProp(obj, propertyKey) { return Object.prototype.hasOwnProperty.call(obj, propertyKey); } const obj = Object.create(null); obj.color = 'green'; obj.age = 2; obj.hasOwnProperty = () => false; console.log(objHasOwnProp(obj, 'color')); // true console.log(objHasOwnProp(obj, 'name')); // falseNo need for that though, as we can use the new built-in
Object.hasOwn()method. Like our reusable function, it takes an object and property as arguments and returnstrueif the specified property is a direct property of the object. Otherwise, it returnsfalse.const obj = Object.create(null); obj.color = 'green'; obj.age = 2; obj.hasOwnProperty = () => false; console.log(Object.hasOwn(obj, 'color')); // true console.log(Object.hasOwn(obj, 'name')); // false8. Error Cause
Error objects now have a
causeproperty for specifying the original error that caused the error about to be thrown. This helps to add additional contextual information to the error and assist the diagnosis of unexpected behavior. We can specify the cause of an error by setting acauseproperty on an object passed as the second argument to theError()constructor.function userAction() { try { apiCallThatCanThrow(); } catch (err) { throw new Error('New error message', { cause: err }); } } try { userAction(); } catch (err) { console.log(err); console.log(`Cause by: ${err.cause}`); }9. Array Find from Last
In JavaScript, we can already use the
Arrayfind()method to find an element in an array that passes a specified test condition. Similarly, we can usefindIndex()to find the index of such an element. Whilefind()andfindIndex()both start searching from the first element of the array, there are instances where it would be preferable to start the search from the last element instead.There are scenarios where we know that finding from the last element might achieve better performance. For example, here we’re trying to get the item in the array with the
valueprop equal toy. Withfind()andfindIndex():const letters = [ { value: 'v' }, { value: 'w' }, { value: 'x' }, { value: 'y' }, { value: 'z' }, ]; const found = letters.find((item) => item.value === 'y'); const foundIndex = letters.findIndex((item) => item.value === 'y'); console.log(found); // { value: 'y' } console.log(foundIndex); // 3This works, but as the target object is closer to the tail of the array, we might be able to make this program run faster if we use the
findLast()andfindLastIndex()methods to search the array from the end.const letters = [ { value: 'v' }, { value: 'w' }, { value: 'x' }, { value: 'y' }, { value: 'z' }, ]; const found = letters.findLast((item) => item.value === 'y'); const foundIndex = letters.findLastIndex((item) => item.value === 'y'); console.log(found); // { value: 'y' } console.log(foundIndex); // 3Another use case might require that we specifically search the array from the end to get the correct item. For example, if we want to find the last even number in a list of numbers,
find()andfindIndex()would produce a totally wrong result:const nums = [7, 14, 3, 8, 10, 9]; // gives 14, instead of 10 const lastEven = nums.find((value) => value % 2 === 0); // gives 1, instead of 4 const lastEvenIndex = nums.findIndex((value) => value % 2 === 0); console.log(lastEven); // 14 console.log(lastEvenIndex); // 1We could call the
reverse()method on the array to reverse the order of the elements before callingfind()andfindIndex(). But this approach would cause unnecessary mutation of the array, asreverse()reverses the elements of an array in place. The only way to avoid this mutation would be to make a new copy of the entire array, which could cause performance problems for large arrays.Also,
findIndex()would still not work on the reversed array, as reversing the elements would also mean changing the indexes they had in the original array. To get the original index, we would need to perform an additional calculation, which means writing more code.const nums = [7, 14, 3, 8, 10, 9]; // Copying the entire array with the spread syntax before // calling reverse() const reversed = [...nums].reverse(); // correctly gives 10 const lastEven = reversed.find((value) => value % 2 === 0); // gives 1, instead of 4 const reversedIndex = reversed.findIndex((value) => value % 2 === 0); // Need to re-calculate to get original index const lastEvenIndex = reversed.length - 1 - reversedIndex; console.log(lastEven); // 10 console.log(reversedIndex); // 1 console.log(lastEvenIndex); // 4It’s in cases like where the
findLast()andfindLastIndex()methods come in handy.const nums = [7, 14, 3, 8, 10, 9]; const lastEven = nums.findLast((num) => num % 2 === 0); const lastEvenIndex = nums.findLastIndex((num) => num % 2 === 0); console.log(lastEven); // 10 console.log(lastEvenIndex); // 4
This code is shorter and more readable. Most importantly, it produces the correct result.
Conclusion
So we’ve seen the newest features ES13 brings to JavaScript. Use them to boost your productivity as a developer and write cleaner code with greater conciseness and clarity.
- Prakhar Vohra, Full stack Developer
Instagram => @webfirex

Comments
Post a Comment