DEV Community

Yaser Adel Mehraban
Yaser Adel Mehraban

Posted on

Useful features of ECMAScript 2019 reviewed

First of all let me apologise for not writing as frequent as I would've liked. It's been a crazy busy couple of weeks and I had heaps of fun speaking at DDD Perth 2019.

That taken care of, this time I thought let's go through the new features which are added into the ECMAScript 2019 (aka ES2019 or ES10), because they're super exciting and make our lives much easier 😎.

TLDR;

At a glance, this version adds a few built-in functions on Array.prototype, flat and flatMap. Then we have Object.fromEntries for directly turning the return value of Object.entries into a new Object.

We also have trimStart and trimEnd on String.prototype over the widely used non-standard versions String.prototype.trimLeft and trimRight.

Another exciting feature is optional catch binding parameters. In addition to those, there are some JSON improvements, addition of Symbol.prototype.description which allows you to specify a description for your symbol, JSON.stringify returns well-formed UTF-8 regardless of input, and at last clarifying Function.prototype.toString by requiring that it either return the corresponding original source text or a standard placeholder.

So if you're ready let's dig in.

Array.prototype.{flat, flatMap}

flat() is a new method which let's you create a one-dimensional array from a multi-dimensional one.

Imagine we have an array like below:

const myArray = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]];
Enter fullscreen mode Exit fullscreen mode

Prior to flat if you wanted to achieve this, you had to do something like this:

const myNewArray = [].concat.apply([], myArray)
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter fullscreen mode Exit fullscreen mode

Or:

var myNewArray = myArray.reduce(
  function(prev,curr) {
    return prev.concat(curr)
  }
)
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter fullscreen mode Exit fullscreen mode

With this new addition, it would be as simple as:

var myNewArray = myArray.flat(4);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter fullscreen mode Exit fullscreen mode

You can also chain multiple calls:

var myNewArray = myArray.flat().flat().flat().flat();
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter fullscreen mode Exit fullscreen mode

The argument into the flat function just specifies how deep it should look into the array. If you're not sure how deep the array is, simply use Infinity as input:

var myNewArray = myArray.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Enter fullscreen mode Exit fullscreen mode

And if you don't provide any input, by default it only goes one level deep:

var myNewArray = myArray.flat(); 
// [1, 2, 3, 4, 5, 6, Array(4)];
Enter fullscreen mode Exit fullscreen mode

flatMap on the other hand, allows you to map each element using a mapping function and then flattens the result into a new array. Think of it as chaining a map function with a single flat. However, it can be really helpful both in terms of usage and efficiency of execution.

let myArray = [1, 2, 3, 4, 5];

let mappedArray = myArray.map(x => [x, x * 2]);
// [Array(2), Array(2), Array(2), Array(2), Array(2)]
// 0: (2)[1, 2]
// 1: (2)[2, 4]
// 2: (2)[3, 6]
// 3: (2)[4, 8]
// 4: (2)[5, 10]

let mappedFlattenedArr = mappedArray.flat();

// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]

let myNewArray = myArray.flatMap(v => [v, v * 2]);
// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
Enter fullscreen mode Exit fullscreen mode

String.prototype.{trimStart, .trimEnd}

These methods are fairly obvious as to what they will do for us. Just keep in mind that we had trimLeft which will be replaced by trimStart and trimRight which will be replaced by trimEnd.

let message = ' This is a string with white space around ';

message = message.trimStart();
// 'This is a string with white space around '

message = message.trimEnd();
// 'This is a string with white space around'
Enter fullscreen mode Exit fullscreen mode

Object.fromEntries

This method get an Iterable and transforms key-value pairs to an object. But let's see what is an Iterable:

JavaScript supports a protocol by which objects such as arrays can be used by control structures such as for…of and the spread operator ... to loop through data sequentially. This is referred to as the iterable and the data structures that support this functionality are called iterables. While JavaScript provides maps, arrays and sets with an iterable property from the get-go, plain objects do not have this by default.

To see this in action:

let entries = new Map([["name", "john"], ["age", 22]]);

let newObj = Object.fromEntries(entries);
// { name: 'john', age: 22 }
Enter fullscreen mode Exit fullscreen mode

A real life use case is when parsing query strings:

let query = Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'));

// { foo: 'bar', baz: 'qux' }
Enter fullscreen mode Exit fullscreen mode

Optional Catch Binding

Optional catch binding allows us to use try/catch without the error parameter inside the catch block.

Previously you had to use this syntax regardless of whether you cared about err or not, such as when you had to fall back to feature to support older browsers:

try {
  // try to use a web feature which may not be implemented
} catch (unused) {
  // fall back to a less desirable web feature with broader support
}
Enter fullscreen mode Exit fullscreen mode

With ES2019 you can do:

try {
  // ...
} catch {
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Symbol.description

This new read-only description property is a string returning the optional description of Symbol objects. This method is encouraged to be used instead of Symbol.prototype.toString
where it wasn't obvious what will be returned.

let description = 'This symbol represents an emoji 😁';

let mySym = Symbol(description);
// Symbol('This symbol represents an emoji 😁')

console.log(mySym.description);
'This symbol represents an emoji 😁'
Enter fullscreen mode Exit fullscreen mode

Function.toString

This method is a really useful one which returns the source code of a function. Imagine doing a troubleshooting on a block of code which is using a third party function. This can potentially help you to see the implementation (given it's got source maps).

function myFn(emoji) {
  let msg = `${emoji} is hellav an emoji`;
  console.log(msg);
}

console.log(myFn.toString());

// "function myFn(emoji) {
//   let msg = `${emoji} is hellav an emoji`;
//   console.log(msg);
// }"
Enter fullscreen mode Exit fullscreen mode

Of course this doesn't work for everything. If we try it for map function on array:

Array.prototype.map.toString();

// "function map() { [native code] }"
Enter fullscreen mode Exit fullscreen mode

Since the implementation is not written in JavaScript, it will just show you that this function is written in native code.

JSON.stringify

The team have done an improvement with Unicode characters and now this method can't return malformed data.

// Non-BMP characters still serialize to surrogate pairs.
JSON.stringify('πŒ†')
// β†’ '"πŒ†"'
JSON.stringify('\uD834\uDF06')
// β†’ '"πŒ†"'

// Unpaired surrogate code units will serialize to escape sequences.
JSON.stringify('\uDF06\uD834')
// β†’ '"\\udf06\\ud834"'
JSON.stringify('\uDEAD')
// β†’ '"\\udead"'
Enter fullscreen mode Exit fullscreen mode

Array.sort Stability

The team has decided to change the sort implementation so that it would be stable (that is, elements that compare equal must remain in their original order).

const grades = [
  { topic: 'math', grade: 10 },
  { topic: 'literacy', grade: 10 },
  { topic: 'chemical', grade: 13 },
  { topic: 'geography', grade: 12 },
  { topic: 'modern history', grade: 12 },
  { topic: 'art', grade: 13 },
  { topic: 'computer basics', grade: 14 },
  { topic: 'algebra', grade: 14 },
];

grades.sort(a, b => a.grade - b.grade);

// 0: {topic: "math", grade: 10}
// 1: {topic: "literacy", grade: 10}
// 2: {topic: "geography", grade: 12}
// 3: {topic: "modern history", grade: 12}
// 4: {topic: "chemical", grade: 13}
// 5: {topic: "art", grade: 13}
// 6: {topic: "computer basics", grade: 14}
// 7: {topic: "algebra", grade: 14}
Enter fullscreen mode Exit fullscreen mode

Summary

In general JavaScript is moving in the right direction for helping developers write more stable, reliable and consistent code. You can find more information on their GitHub repo here.

Hope to see more awesome features in JavaScript and see you soon with another article.

Top comments (7)

Collapse
 
kataras profile image
Gerasimos (Makis) Maropoulos • Edited

Although I am not a frontend or node developer (except things like github.com/kataras/neffos.js). I found this article very useful for people like me - to stay up-to-date and learn about all major technologies even if we don't use them in our daily life. Nice article mr Yaser!

Collapse
 
yashints profile image
Yaser Adel Mehraban

Thanks

Collapse
 
drewtownchi profile image
Drew Town

When do people find themselves using/needing .flat()? I don't think I've ever run into a scenarios where I have nested arrays that I need flattened?

I'm curious as to other's experiences when they find they need flat.

Collapse
 
rudolfolah profile image
Rudolf Olah

If you're dealing with tree structures, like in a nested JSON data object, you may want to select deeply nested items across multiple sub-structures and then use flat() to flatten the array. An example in Ruby is flattening a list of data attributes from a database request. If you're using es2019 on the backend with node.js, flat() could be useful in that case.

Collapse
 
rbauhn profile image
Robin Bauhn

I very rarely use it but I actually did it yesterday. Most often it's when I run multiple queries to GCP's Firestore (because they don't have OR statements...) and get a bunch of arrays with results in an array with all the promises that I await to let them resolve. Then I have a nested array which is quite neat to flatten.

Collapse
 
yashints profile image
Yaser Adel Mehraban

A couple of common use cases are:

  1. Image data manipulation
  2. Machine learning data prep
  3. Working 2D or 3D shapes
  4. Searching for an element in a nested array without multiple loops
Collapse
 
schaan profile image
Schaan Alq. • Edited

Exactly. I see it is like a preparation for js getting into the two hot topics:

  1. data science;
  2. VR (computational geometry)