ECMAScript 2019 and beyond...
Tags: javascript, ecmascript, webdev
Published: 2019-07-05 11:27:48

**This post was taken from [my blog](https://areknawo.com), so be sure to check it out for more up-to-date content.**

Last month - June 2019 -  [10th edition of ECMA-262](https://www.ecma-international.org/ecma-262/10.0/)  standard was officially published. What does it mean? - Well,  **ECMAScript 2019**  is here! The latest and greatest specification for JavaScript and other derivatives languages to follow. And while you may already have heard of some of its new features, we'll recall all of them! Plus some ECMAScript details and a sneak-peak of what's coming next!

# Release cycle

While we already know  [what ECMAScript is](https://areknawo.com/javascript-is-dead-long-live-ecmascript/), and how it's now-yearly release cycle works, there are some more interesting things to it.

Surely the release of every new ES specification is important, but it's recommended not to look at it as a once-per-year thing (unless you're living in pre-ES6 era). The specification is "alive",  [being worked on](https://tc39.es/ecma262/)  as you're reading this. Every release is just a summary of a bunch of new  **features**. And that's how you should look at it - feature by feature.

You might know by now (possibly due to working with Babel before) that ECMAScript specification is created as a result of different  [**proposals**](https://github.com/tc39/proposals). Each proposal needs to go through 5 different stages...

Every new proposal starts its life as merely an idea, which needs to first be reviewed by  [**TC39**](https://tc39.es/). This committee consists of experts and representatives of different companies/organizations (like Google and Mozilla) and decides about the future of the specification. When the submitted idea is positively reviewed, it goes to  **stage-0**. From now on, it's public and available from the corresponding  [GitHub repo](https://github.com/tc39/proposals/blob/master/stage-0-proposals.md). As the proposal is discussed further and further at regular  [TC39 meetings](https://github.com/tc39/tc39-notes), it either gets to the next stage or is abandoned in the process. Proposals at  [**stage-3**](https://github.com/tc39/proposals#stage-3)  can be considered to be very stable and assured. After the proposal reaches  **stage-4**_,_  it's official.

Now, all this process - different stages and stuff - doesn't necessarily match the implementation time. Many browser vendors in order to keep their browser ever-green and appealing to developers, often implement features even when they're still at the stage-3. Naturally, as such features are still non-standard, many people will most likely either use  **Babel**  or won't use the feature at all! But still, it's a fact. With that said, some features may even be implemented a while after the official specification drops. But, since the last  _"big"_  release of ES (ES6), such things don't take place very often.

# ECMAScript 2019

With ES release cycle out of the picture, let's explore all new features of ES2019! I know that you might already have seen these before, but, please, let's bear with me for a moment as we're going to do this once more, in a beginner-friendly manner!

## [Array.prototype.flat{Map}()](https://v8.dev/features/array-flat-flatmap)

As I mentioned earlier, many of ES2019 features can appear in browsers before the official specification drops. That's the case with two new immutable  [array methods](https://areknawo.com/map-reduce-filter-my-turn/)  -  [`.flat()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat)  and  [`.flatMap()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap).

Now, I've covered these methods  [a while back](https://areknawo.com/exploring-the-hidden-potential-of-javascript-arrays/), so check that out if you want to learn more. Here's a little refresher!

```javascript
const arr = [1, [2, [3, 4]]];

arr.flat(2); // [1, 2, 3, 4]
arr.flatMap(num => `${num}`); // ["1", "2,3,4"]
```

I think the naming of these methods reveal all there is to them.  `.flat()`  can be used to  **flatten** your multi-dimensional array. By default, it does it 1 level deep, but you can optionally pass an argument to specify the deepness, as we did in the example above.

Because calling  `.flat()`  in combination with  [`.map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)  can be very useful, there's a special method for that too! -  `.flatMap()`. This guy maps the array first and then flattens it 1 level deep (no configuration here). And all of that comes with the improved performance of course!

## [Object.fromEntries()](https://v8.dev/features/object-fromentries)

With the introduction of  [`Map`  objects](https://areknawo.com/rocking-js-data-structures/)  in ES6 and the need of representing the data with arrays in key-value fashion,  [`Object.fromEntries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries)  can prove to be quite useful when doing such operations. It can change your Array or Map of key-value pairs (entries) into an actual object - something that before ES2019 required custom code.

```javascript
const arr = [
    ["key1", "value1"],
    ["key2", 2],
    ["key3", {value: 3}]
];

Object.fromEntries(arr); 
// { key1: "value1", key2: 2, key3: { value: 3 } }
```

## String.prototype.trimStart() and more...

ES5  [`.trim()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)  method has 2 new colleges, or even 4! While  `.trim()`  was  **removing unnecessary spaces**  from both sides of the string, now there're some new methods to do that form only the specified one!

[`.trimStart()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart), also known as  `.trimLeft()`, can be used to trim the string from its start/left side...

```javacript
const str = "     str     ";

str.trimStart(); // "str     "
str.trimLeft(); // "str     "
```

while  [`.trimEnd()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd)  and  `.trimRight()`  can be used to do the same, from the right side.

```javascript
const str = "     str     ";

str.trimEnd(); // "     str"
str.trimRight(); // "     str"
```

## Optional catch binding

Apart from bringing us only a few new methods, ES2019 fixes some flaws of its predecessors. First one being the requirement to include error parameter in  `try`/`catch`  statements, even when not using it.

```javascript
// then
try {
    // ...
} catch(error) {
    // ...
}

// now
try {
    // ...
} catch {
    // ...
}
```

The less code to write the better, right?

## Function.prototype.toString();

In ES-based languages, you can  `.toString()`  pretty much all the things! What its different calls will resolve in is a whole another story. But, up to ES2019, when used with functions,  [`.toString()`](https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Function/toString) returned a string with the function's code only. Now, it also takes into account comments, new lines, and whitespaces - everything!

```javascript
function toBeStringified() {
    // a comment
    
    // a comment after new line
}

toBeStringified.toString();
/*
`function toBeStringified() {
    // a comment
    
    // a comment after new line
}`
*/
```

## [Symbol.prototype.description](https://v8.dev/features/symbol-description)

[`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)  - always-unique data type used mostly as object's properties identifier - just got a new property called  `.description`. It can be used to access the  `Symbol`'s optionally-passed description parameter, in the form of a string.

```javascript
const mySymbol = Symbol(2);

mySymbol.toString(); // "Symbol(2)"
mySymbol.description; // "2"
```

## [Array.prototype.sort()](https://v8.dev/features/stable-sort)

If you've used  [`.sort()`](https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Array/sort)  before, you might know that it's a recommended practice not to rely on its default  **sorting algorithm**. That's because there was no mention of any  **stability**  requirements for the algorithm, in the previous specifications. Now, in ES2019, that  _"stable sort"_  is required by specs, every JS engine needs to comply with it. That means that they still can use different algorithms, but there shouldn't be any misconceptions related to that. To see what I mean - check out the example below.

```javascript
const dogs = [
  { name: "Abby",   rating: 12 },
  { name: "Bandit", rating: 13 },
  { name: "Choco",  rating: 14 },
  { name: "Daisy",  rating: 12 },
  { name: "Elmo",   rating: 12 },
  { name: "Falco",  rating: 13 },
  { name: "Ghost",  rating: 14 },
];

// Sort the dogs by `rating` in descending order.
dogs.sort((a, b) => b.rating - a.rating);
/* 
[
  { name: "Choco",  rating: 14 },
  { name: "Ghost",  rating: 14 },
  { name: "Bandit", rating: 13 },
  { name: "Falco",  rating: 13 },
  { name: "Abby",   rating: 12 },
  { name: "Daisy",  rating: 12 },
  { name: "Elmo",   rating: 12 },
]
*/
```

As you can see in the result comment above, the array is sorted  _"as expected"_  by our sorting function. In the original one - the items were sorted alphabetically by the  `name`  field. Now, they're sorted by  `rating`  first, but they're still in alphabetical order. The second fact is kind-of expected (sorted items should respect their previous positions), but it wasn't guaranteed before ES2019. From now on, new browsers will assure you the right order. But know that the old ones are still out there. That's why you should be very explicit when writing your sorting functions and not necessarily depend on the browser's default behavior too much.

## [A word on JSON...](https://v8.dev/features/well-formed-json-stringify)

JSON and JSON-related functionalities got a little revision too!

`JSON.stringify()`  now properly escapes Unicode  _["lone surrogates"](https://unicode-table.com/en/blocks/high-surrogates/)_. This isn't such a big deal, considering that you might hardly ever encounter issues related to that. Still, it's one thing to think about less when writing your code. To give you an example:

```javascript
// then
JSON.stringify('\uD800'); // "'�'"

// now
JSON.stringify('\uD800'); // "'\\ud800'"
```

There's yet another issue with Unicode strings that was fixed with ES2019! JSON is usually considered a subset of ECMAScript, but it wasn't entirely true up until this point. JSON strings could contain some unescaped Unicode characters (_U+2028_  and  _U+2029_), while ES strings could not. Now,  [ES supports these characters](https://github.com/tc39/proposal-json-superset), the issue is fixed, and JSON is truly a subset of ES.

# What the future holds?

Now that we've covered all of the ES2019 goodness - what's next? New features are constantly being introduced to modern browsers engines (like V8), even when they're only at stage-3! Some of them are already scheduled for  **ES2020**, others - not so much. But, I'd like to give you a small glimpse of the future which, in some cases, can be experienced right now! With that said, here's 3 most interesting features to look forward to in ES2020 and beyond!

## [Dynamic import()](https://v8.dev/features/dynamic-import)

From what I know, many developers still use code bundlers, even with ES modules being officially supported by all major browsers. But who can blame them? Modules really need some more  _"standardization"_  - not from the specification, but from the community. And for that, some time needs to pass and old browsers have to die...

But, so-called dynamic  `import()`  is definitely going to part of this  _"modular future"_. Well... maybe future is a bit too bold of a term, considering that this feature has already been implemented by  [all major browsers](https://caniuse.com/#feat=es6-module-dynamic-import)  and is at  **stage-4**, scheduled for  **ES2020**.

```javascript
import("module.mjs")
    .then((module) => {
      module.default(); // export default stuff
      module.doStuff(); // other stuff
    });
```

The main advantage of dynamic  `import()`  is the fact that loading modules is done in a lazy manner. In this way, you can significantly improve your app's performance, just by loading the necessary stuff first (with standard  `import`  statements), and everything other later. Plus, they're almost unnoticeable in syntax when done with  `async`/`await`!

```javascript
(async () => {
    const module = await import("module.mjs")
    module.default();
    module.doStuff();
})();
```

## [BigInt](https://v8.dev/features/bigint)

Dealing with large numbers in JS can be pretty problematic. The range of possible values is big, but, in some cases, it's just not enough. And that's why  [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)  was born!

`BigInt`  is a completely  **new numeric primitive**  that works alongside currently-available  `Number`. It's already  [implemented in Chromium-based and some other browsers](https://caniuse.com/#feat=bigint), but that's pretty much it. The support will definitely grow once  `BigInt`  gets beyond stage-3 and becomes official seemingly with ES2020.

For now, until the support gets better, I think all you need to know is that you'll be able to express some big numbers in JS with great performance, without any 3rd-party library!

```javascript
BigInt(Number.MAX_SAFE_INTEGER) + 2n; // 9007199254740993n
/* Value bigger than Number can represent
   BigInts can be created with -n suffix */
```

Of course, as the name implies,  `BigInt`  can only be used to represent integers. This makes me really look forward to possible  _BigDecimal_  (or something like that) in the future...

## [Private class fields](https://v8.dev/features/class-fields)

Probably one of the most awaited features of ES. Private class fields are something that many developers really want. The ability to hide the implementation details for real!

Private class fields are currently at stage-3. It's yet unsure if we'll see them in ES2020 or not. But, despite how awesome of a feature this might be, I still have some concerns about it. First, by current proposal, there's no mention of any kind of  **protected fields**  - those who use TypeScript or some other statically-typed language know what I'm talking about. And, what's even worst - the syntax for private fields in ES proposal is just... bad IMHO. The cross-language untold  _"standard"_  of  `public`,  `protected`  and  `private`  keywords is replaced by a hash (`#`) symbol. Even though, I'm still happy that such feature (in any shape or form) is coming to JS!

```javascript
class IncreasingCounter {
    #count = 0;
    get value() {
        console.log("Getting the current value!");
        return this.#count;
    }
    increment() {
        this.#count++;
    }
}
```

# Want to know more?

ES specification and proposals are evolving every day. So do browsers and JS engines. If you want to be up-to-date with the latest and greatest features, I encourage you to check out  [v8.dev](https://v8.dev/features)  blog, where people behind  **V8**  share very insightful information about the engine, its latest features and how they were implemented. Highly recommended!

So, that's it for this article. Consider following me  [**on Twitter**](http://twitter.com/areknawo),  [**on my Facebook page**](http://facebook.com/areknawoblog), or checking out [**my personal blog**](https://areknawo.com)  for more awesome content. And, as always, have a great day!