What's new in ES2019
ECMAScript (ES) is the specification on which JavaScript is based. This language is constantly evolving and receiving updates every year. It is useful to keep up to avoid being stumped by syntax and stay productive in any JavaScript codebase.
ES2019 is available in the latest version of Chrome, Firefox, Safari, and Node. It is also available in older platforms via compilation with Babel or Typescript. Remember to always check Can I Use website to make sure the new feature you want to use is available in your target platforms.
- Array.flat()
- Array.flatMap()
- String.trimStart()
- String.trimEnd()
- Object.fromEntries
- Optional Catch Binding
- Symbol.prototype.description
- Function.prototype.toString()
- JSON improvements
Array.flat()
The flat()
method returns a new array flattering all the sub-array elements recursively up to the specified depth.
const a1 = [1, 2, [3, 4], 5];
console.log(a1.flat()); // OUTPUT: [1, 2, 3, 4, 5]
By default it only flats one level flat(1)
, but you can convert any Array
multi-dimensional to one-dimension using Infinity
.
const a2 = [1, 2, [[3, [4, 5]], 6], 7];
console.log(a2.flat(Infinity)); // OUTPUT: [1, 2, 3, 4, 5, 6, 7]
And, if you have an empty element as part of you Array
, it'll be removed in the new Array
const a3 = [1, 2, , 5];
console.log(a3.flat()); // OUTPUT: [1, 2, 5]
Array.flatMap()
It returns a new array combining flat()
and map()
methods. Remember: ES6 map()
method of an Array
returns a new Array
applying a function to each of its elements.
Suppose we want to double each element of an array and put the result after each one of these elements:
const b1 = [2, 8, 32];
const b2 = b1.map(el => {
return [el, el * 2];
});
console.log(b2); // OUTPUT: [[2, 4], [8, 16], [32, 64]]
const b3 = b2.flat();
console.log(b3); // OUTPUT: [2, 4, 8, 16, 32, 64]
Using flatMap()
const b4 = [2, 8, 32];
const b5 = b4.flatMap(el => {
return [el, el * 2];
});
console.log(b5); // OUTPUT: [2, 4, 8, 16, 32, 64]
String.trimStart() and String.trimEnd()
String.trim()
removes the whitespaces from the beginning and the end of a String
so using String.trimStart()
will only remove the whitespaces from the beginning of the string while use String.trimEnd()
will do but with the whitespaces from the end.
const c1 = ' Start here. ';
const c2 = c1.trimStart();
console.log(c2); // OUTPUT: 'Start here. ' (with the spaces at the end)
const c3 = ' End here. ';
const c4 = c3.trimEnd();
console.log(c4); // OUTPUT: ' End here.' (with the spaces at the beggining)
Object.fromEntries(iterable)
This method only accepts an iterable
as argument and it creates an Object
from a list of key-value pairs e.g. produced by Object.entries()
(ES2017) which is used to transform an Object
to an Array
of [key, value] pairs.
Suppose we want double each value of the properties of an object:
const d1 = {
prop1: 2,
prop2: 8,
prop3: 32
};
const d2 = Object.entries(d1);
console.log(d2); // OUTPUT: [["prop1", 2], ["prop2", 8], ["prop3", 32]]
With map()
we can iterate over each element and apply the function to double each value:
const d3 = d2.map(([key, value]) => [key, value * 2]);
console.log(d3); // OUTPUT: [["prop1", 4], ["prop2", 16], ["prop3", 64]]
Now, using fromEntries()
method we will generate the Object
with the values changed.
const d4 = Object.fromEntries(d3);
console.log(d4);
/* OUTPUT:
{
prop1: 4,
prop2: 16,
prop3: 64,
}
*/
Optional Catch Binding
It allows to use the catch()
clause without the need to specify the parameter (the exception).
try {
// execute code
} catch {
// handle error
}
There is no need to add the parameter to the catch()
(optional)
try {
// execute code
} catch (err) {
// handle error
}
Symbol.prototype.description
It allows to provide a description when creating a Symbol
via the factory function Symbol()
and access to it via the description property.
const e1 = Symbol('Optional description');
console.log(e1.description); // OUTPUT: 'Optional description'
Function.prototype.toString()
It returns the function exactly as it was defined including withespaces and comments.
Previous ES10
const fn = function /* initial test */ test() {};
fn.toString(); // OUTPUT: 'function test() {}'
Now it will be:
const fn = function /* initial test */ test() {};
fn.toString(); // OUTPUT: 'function /* initial test */ test() {}'
JSON improvements
The line separator \u2028
and paragraph separator \u2029
symbols now parse correctly instead of resulting in a SyntaxError when using using JSON.parse()
Well-formed JSON.stringify
Prevent JSON.stringify from returning ill-formed strings (specifically, surrogate code points U+D800 through U+DFFF).
Flatmap… oh, the JS cousin of C#'s SelectMany! mmmm someone should make an article comparing Js Array functions with linq ones, mostly to help C# devs to get a quick grip on those since they’re similar :)
trimStart() and trimEnd()… wat!!! What would possess someone call these functions that? What’s wrong with time-tested, “industry standard” ltrim() and rtrim()?
-> rtrim & ltrim are not verbose -> ya… but everyone already knows them from basically every other language AND they are clearly trimming from the LEFT and from the RIGHT; Start and End are assumed to be left and right but then someone writing a multi-lang app dealing with right-to-left languages will have to use trimEnd() to trim the START of this text…
Looks like they forgot that there are people developing apps for right-to-left languages, looks like for those cases people will have to do some polyfill of the
String.prototype.leftTrim = String.prototype.trimStart
kind XD.