ECMAScript 2019, also known as ES2019, is the tenth edition of the ECMAScript Language Specification. This version of the specification introduced several new features that improved the functionality of JavaScript. In this article, we will take a closer look at some of the new features introduced in ES2019, and provide code examples to illustrate how they can be used.
Array.flat() and Array.flatMap()
The Array.flat() method can be used to flatten multidimensional arrays into a single-dimensional array. It takes an optional argument that specifies the depth of the recursion. If no argument is specified, the default depth is 1.
Here’s an example that demonstrates how Array.flat() works:
const arr = [1, 2, [3, 4, [5, 6]]];
const flattened = arr.flat();
console.log(flattened); // [1, 2, 3, 4, [5, 6]]
The Array.flatMap() method works in a similar way to Array.map(), but it first maps each element using a mapping function, and then flattens the result into a single-dimensional array. Here’s an example that demonstrates how Array.flatMap() works:
const arr = [1, 2, 3, 4];
const mapped = arr.flatMap(x => [x * 2]);
console.log(mapped); // [2, 4, 6, 8]
Object.fromEntries()
The Object.fromEntries() method can be used to create an object from an array of key-value pairs. Here’s an example that demonstrates how Object.fromEntries() works:
const entries = [['a', 1], ['b', 2], ['c', 3]];
const obj = Object.fromEntries(entries);
console.log(obj); // { a: 1, b: 2, c: 3 }
String.trimStart() and String.trimEnd()
The String.trimStart() and String.trimEnd() methods can be used to remove whitespace from the beginning and end of a string, respectively. Here’s an example that demonstrates how String.trimStart() and String.trimEnd() work:
const str = ' Hello, World! ';
const trimmedStart = str.trimStart();
const trimmedEnd = str.trimEnd();
console.log(trimmedStart); // 'Hello, World! '
console.log(trimmedEnd); // ' Hello, World!'
Optional catch binding
ES2019 introduced the ability to omit the parameter in a catch block. This can be useful when you don’t need to reference the error object.
Here’s an example that demonstrates how optional catch binding works:
try {
// some code that might throw an error
} catch {
// handle the error
}
In the above example, the error object is not referenced, so we can omit the parameter in the catch block.
JSON improvements
ES2019 introduced several improvements to JSON, including the ability to serialize and deserialize BigInt values, and the ability to control the sorting order of object keys using the replacer function.
Here’s an example that demonstrates how JSON improvements work:
const obj = {
a: 1n,
b: 2n,
c: 3n
};
const json = JSON.stringify(obj, null, 2);
console.log(json); // '{"a":1,"b":2,"c":3}'
const parsed = JSON.parse(json, (key, value) => {
if (typeof value === 'number') {
return value * 2;
} else {
return value;
}
});
console.log(parsed); //
Optional chaining
One of the most significant additions to ECMAScript 2019 is optional chaining. It is a feature that simplifies the process of checking for nested properties and avoids errors when accessing nested properties of an object that may not exist.
Optional chaining is denoted by a question mark (?) that can be placed before the dot (.) operator used to access properties. It allows developers to safely access a deeply nested property of an object, even if the intermediate properties are undefined or null.
Here is an example of how optional chaining can simplify your code:
let person = {
name: "John",
address: {
city: "New York"
}
};
let country = person.address?.country;
console.log(country); // undefined
In the above example, we are trying to access the country
property of the address
object, but it doesn't exist. Using optional chaining, we can simply add a question mark before the dot operator to check if the address
object exists, and if not, return undefined.
This feature can also be used with function calls. Here is an example:
let person = {
name: "John",
getAge: function() {
return 30;
}
};
let age = person.getAge?.();
console.log(age); // 30
In this example, we are trying to call the getAge
method of the person
object. However, if the getAge
method does not exist, an error will occur. By using optional chaining, we can safely call the method without an error.
Overall, optional chaining is a great addition to ECMAScript 2019 as it simplifies the process of checking for nested properties and makes the code more readable and maintainable.
Nullish coalescing
Another significant addition to ES2019 is the nullish coalescing operator (??
), which is used to provide a default value for variables that are null or undefined. The ??
operator checks if a value is either null or undefined, and if so, it returns a default value.
Here’s an example that demonstrates how the nullish coalescing operator works:
// without nullish coalescing
let foo;
console.log(foo || 'default'); // 'default'
foo = null;
console.log(foo || 'default'); // 'default'
foo = '';
console.log(foo || 'default'); // 'default'
foo = 0;
console.log(foo || 'default'); // 'default'
// with nullish coalescing
let bar;
console.log(bar ?? 'default'); // 'default'
bar = null;
console.log(bar ?? 'default'); // 'default'
bar = '';
console.log(bar ?? 'default'); // ''
bar = 0;
console.log(bar ?? 'default'); // 0
In the first set of examples, the logical OR operator (||
) is used to provide a default value for the foo
variable. However, this approach has a flaw, because the ||
operator considers any falsy value, such as ''
or 0
, to be equivalent to null or undefined.
In the second set of examples, the nullish coalescing operator (??
) is used to provide a default value for the bar
variable. The ??
operator only considers null
or undefined
values to be missing, so it returns the default value only if the variable is null or undefined. This approach is more precise and less error-prone than using the ||
operator for default values.
Conclusion
In conclusion, ES2019 introduced a number of useful features to the language, including optional chaining, nullish coalescing, Array.prototype.flat()
, String.prototype.trimStart()
and String.prototype.trimEnd()
, and Object.fromEntries()
. These features can help simplify your code and make it more concise and readable.