What‘s New in JavaScript ES2019: A Developer‘s Guide

JavaScript, the language that powers much of the modern web, is continually evolving thanks to the dedicated efforts of the TC39 standards committee. With the official release of ECMAScript 2019, or ES10 for short, JavaScript has gained a number of useful new features that developers can start leveraging in their code today. In this in-depth post, we‘ll explore what has changed and how you can put these new capabilities to work.

The ECMAScript Standards Process

Before we jump into the new features, let‘s take a quick look at how additions make their way into JavaScript. It all revolves around the ECMAScript specification, the standardized definition and implementation of the JavaScript language maintained by TC39, or Technical Committee 39. This committee is made up of members from browser vendors, large companies, and the JavaScript community.

Representatives can submit proposals for new JavaScript syntax or built-in functionality to be considered for inclusion in the official specification. Each proposal goes through a strict 5-stage process:

  • Stage 0: Strawperson – The initial idea for a feature, submitted via an issue or pull request to the TC39 proposals repository
  • Stage 1: Proposal – A formalized proposal championed by a TC39 member, including a high-level API description, examples, and discussion of potential issues
  • Stage 2: Draft – The proposal is formalized further into a detailed draft specification, an initial implementation is created, and the committee agrees the idea is worth including
  • Stage 3: Candidate – The proposal is mostly finalized and needs feedback from implementations and users to progress further
  • Stage 4: Finished – The proposal is ready to be included in the formal ECMAScript standard when the next version is released

By having new additions go through this rigorous multi-stage process, it helps ensure only high-quality, well-specified, and broadly useful features make it into the rapidly evolving JavaScript language. With that background in mind, let‘s take a look at the headline features that made it through to be included in ES2019.

New JavaScript Features in ES2019

Array.prototype.flat() and flatMap()

The new flat() method enables you to easily concatenate all sub-array elements of an array recursively up to a specified depth. This can be useful for flattening nested arrays.

The flat() method accepts an optional argument specifying how deep the flattening should recursively go. If no depth is provided, the default is 1. You can also pass in Infinity to flatten the array all the way down.

Here are a few examples:


const nestedNumbers = [1, 2, [3, 4, [5, 6]]];

// Flatten one level deep nestedNumbers.flat(); // [1, 2, 3, 4, [5, 6]]

// Flatten two levels nestedNumbers.flat(2); // [1, 2, 3, 4, 5, 6]

// Flatten recursively nestedNumbers.flat(Infinity); // [1, 2, 3, 4, 5, 6]

The related flatMap() method first maps each element of an array using a mapping function, then flattens the result into a new array. It combines map() and flat() into a single operation.


const numbers = [1, 2, 3];

// map() and flat() separately numbers.map(num => [num, num 2]); // [[1, 2], [2, 4], [3, 6]] numbers.map(num => [num, num 2]).flat(); // [1, 2, 2, 4, 3, 6]

// Using flatMap() numbers.flatMap(num => [num, num * 2]); // [1, 2, 2, 4, 3, 6]

These new methods provide a more elegant and succinct way to deal with nested arrays compared to manually looping or using a customrecursive flattening function.

Object.fromEntries()

Object.fromEntries() transforms a list of key-value pairs into an object, essentially acting as the reverse of Object.entries(). This makes it a convenient way to convert other data structures like Maps or Array.prototype entries into plain objects.

The method takes an iterable of key-value pair entries, like an Array or Map, and returns a new object whose properties are given by those entries. Here‘s an example:


const fruitColors = [
  [‘apple‘, ‘red‘],
  [‘banana‘, ‘yellow‘], 
  [‘grape‘, ‘purple‘]
];

// Convert Array to Object const fruitColorMap = Object.fromEntries(fruitColors); // { apple: ‘red‘, banana: ‘yellow‘, grape: ‘purple‘ }

// Convert back to Array Object.entries(fruitColorMap);
// [[‘apple‘, ‘red‘], [‘banana‘, ‘yellow‘], [‘grape‘, ‘purple‘]]

This can be particularly handy when working with function that return key-value pair Arrays, like Object.entries() or Map.prototype.entries(), and you need to convert the result back into an Object.

String.prototype.trimStart() & trimEnd()

The trimStart() and trimEnd() methods trim whitespace from the beginning and end of a string respectively. They work similarly to the existing String.prototype.trim() method, but provide finer-grained control.


const message = "   Hello JavaScript!   ";

message.length; // 23

message.trimStart(); // "Hello JavaScript! "

message.trimEnd();
// " Hello JavaScript!"

message.trim(); // "Hello JavaScript!"

These methods make it more concise to remove leading or trailing whitespace from strings without resorting to regular expressions or manual manipulation.

Optional Catch Binding

ES2019 made a small but useful change to the catch syntax used with try/catch statements. Previously, you had to specify an exception binding parameter, even if your catch block didn‘t actually use it.

The new optional catch binding syntax lets you omit the parameter if you don‘t need to access the caught error object:


// Old syntax
try {
  // ...
} catch (error) {
  // error is required  
}

// New in ES2019 try { // ... } catch { // No parameter needed }

This is purely a syntactical enhancement, but it cleans up catch blocks where you want to fully ignore the thrown error. Just be careful not to omit the binding if you do actually need to log or handle the error in some way.

JSON ⊂ ECMAScript

The ECMAScript language specification now officially supports a broader set of valid JSON text. Specifically, it allows unescaped line and paragraph separators (U+2028 and U+2029) to appear in JSON-formatted strings.

Previously, using these unescaped separators could lead to SyntaxError exceptions when parsing JSON. JSON text generated by ECMAScript‘s JSON.stringify() now properly escapes these separators for maximum compatibility.


// Invalid in ES2018 and earlier  
const oldJson = ‘{ "line": "\u2028" }‘;
JSON.parse(oldJson); // SyntaxError

// Valid in ES2019 const newJson = ‘{ "line": "\u2028" }‘;
JSON.parse(newJson); // { line: ‘\u2028‘ }

While somewhat obscure, this change helps improve compatibility and reduce friction between the JSON and ECMAScript standards. It‘s good news if you work heavily with JSON data.

Function.toString() Revision

The Function.prototype.toString() method has been updated to return a more precise representation of function source code. Previously, toString() returned a condensed, stripped-down version of a function without whitespace, comments, or other original formatting.

As of ES2019, toString() now returns the exact source text slice used to define the function, including any whitespace and comments present. This change primarily benefits debugging, logging, and other meta-programming use cases.


function /* Demo */ foo () {}

// Old behavior foo.toString(); // "function foo() {}"

// New in ES2019 foo.toString();
// "function / Demo / foo () {}"

Being able to reliably access a function‘s exact source can be incredibly useful for introspection, documentation generation, and other tooling needs.

Symbol.prototype.description

ES2019 introduced a read-only description property on Symbol objects to retrieve a Symbol‘s optional description string.

Symbols are often used as unique property keys on objects, and can be given an optional description parameter when created to provide debug information. The new description property exposes this internal description directly:


const testSymbol = Symbol(‘Test‘);

testSymbol.toString(); // "Symbol(Test)"

testSymbol.description; // "Test"

Symbol(‘‘).description;
// ""

Symbol().description;
// undefined

This addition is mainly helpful for logging and debugging code that works with Symbols. By having access to a Symbol‘s descriptive string, you can more easily determine a Symbol‘s purpose.

Upcoming ECMAScript Proposals

Those were the major features that landed in ES2019, but there are always new proposals flowing through the ECMAScript pipeline. At the time of writing, some proposals at Stage 3 that may make it into ES2020 or beyond include:

  • Private and static class fields and methods
  • Top-level await in modules
  • WeakReferences for more flexible object lifecycles
  • Unified global ThisBinding

You can track the progress of all active proposals in the official TC39 proposals GitHub repository.

Conclusion

JavaScript remains a living, evolving language thanks to the work of the TC39 committee and the ECMAScript standardization process. ES2019 brings both incremental quality-of-life improvements and foundational upgrades to the language.

As a developer, it‘s important to stay on top of these changes and understand how they impact the code you write. Hopefully this post has given you a solid overview of what‘s new and noteworthy in ES2019.

From here, your best next steps are to try out these new features in your own projects, provide feedback, and keep an eye on upcoming proposals. The JavaScript ecosystem thrives thanks to the active involvement of the developer community. Together, we can help guide the future of this influential language.

Similar Posts