It seems everything is changing – even the naming of releases has changed, with years marking the language version.
And starting with the release of ES6 (officially, “ES2015”), the language has has continued to evolve at a rapid pace, introducing a staging system to mark the progress of features and changes.
But which features should you be using now? Or soon?
The ES2016+ Short List
My short list of features could stretch all the way back to ES6 – but then it wouldn’t be a very short list.
- Object Rest / Spread Properties
- Async functions
While there are many other great changes that can benefit your work on a day-to-day basis, this short list stands to make an incredible difference in your work.
Object Rest / Spread Properties
How many times have you added underscore.js or lodash to your project, just to get the “.extend” method? I lost count years ago…
At it’s core, Object Rest Properties is an update to destructuring assignment, which allows you to take many values out of object properties and assign them individually to variables, with one line of code:
With the changes in Object Rest Properties, you can now get the “rest of the properties” from an object, when doing destructuring assignment, as a new object.
Destructuring assignment is an important feature in reducing syntax noise and clarifying the intent of code.
But what if you want to “re”-structure multiple objects into a new object? With Object Spread Properties, you can do that easily:
With this, you no longer need underscore.js or lodash to get the “extend” method. You can easily create a shallow copy of an object using Object Spread Params, instead.
Just be aware that like underscore and lodash, Object Spread is “last one in wins” – meaning if an object at the end of the list (on the right) has the same property as a previous object in the list, the previous value will be overwritten.
Have you ever tried to mix native DOM events, jQuery events, events from a framework like Backbone or Ember, and other events from other code?
And when creating event handlers in these frameworks and libraries, have you ever noticed that sometimes your handler fires twice (or more) for the events?
In the past, developers had to be keenly aware of the pitfalls of memory leaks, manually removing the event handlers at the right time. As time moved on, framework developers got smart and started wiring up the magic of unregistering event handlers for you.
But the problem of mismatched API design remains… and can throw some serious wrenches in the code that is supposed to handle the registering and unregistering of event handlers.
In this example, there are 2 observable objects.
The first listens to a browser window being resized through the DOM API directly
The second listens to an object’s custom event system
While the underlying code for these two events is very different, both of these observable objects share an API that can be used anywhere that supports observables.
This is important for two reasons.
First, the common API for an observable means you can adapt nearly any data source – a custom API, a stream of data, a different event source, and more – into an observable. When you want to use the data source, you no longer have to worry about the API design. It’s the same for all observables.
Second, the API standard for an observable includes a method to remove or unregister the events / stream from the underlying code. This means you now have a common way to clean up your event handlers, no matter where the events are coming from.
No more memory leaks due to mismatched API design or forgetting to unregister your handlers (unless you don’t implement the method call in your observable, of course).
(Note the difference in the Observable implementation in this version, to account for removing the event handlers when “unsubscribe” is called)
There’s a lot of power behind observables that can’t be shown here, however. For more information on how they work, how they’re built, etc, check out this interview and demonstration with Chet Harrison, on functional reactive programming.
Of all the features in ES2016+, async functions are by far the biggest game changer. If you only learn one thing from this article, it should be that you need to start using async functions as soon as possible.
Why, you ask?
Nested function after nested function. Multiple redundant, but necessary, checks for errors. It’s enough to make you want to quit… and this is a simple example!
Imagine if your code could look like this, instead:
Now that looks nice! So much easier to read – as if the code were entirely synchronous.
The good news is that It only takes a few additional keywords to make this work in async functions:
By adding “async” to the outer function definition, you can now use the “await” keyword to call your other async functions. The functions that are called with “await” must also be marked as “async”, and there’s one more key to making them work: promises.
It’s common to use callbacks to enable asynchronous code. And I’ve often said that this is preferable to using promises. But with async functions, promises are now the way to go.
By returning a promise from an async function, it can now be consumed with the “await” keyword, as shown above. The end result is code that is far easier to read and understand, easier to maintain, and easier to deal with as a developer.
How To Use These Features, Today.
For the features mentioned here, you can start using them today. Even if the feature definition is not 100% complete, there is enough value and enough support to make it both easy and safe to use.
Object Rest / Spread Properties:
The syntax change behind destructuring and restructuring may help us reduce the amount of code we have to write (or reduce the number of libraries we have to bring along with our code) when assign multiple values to variables, and when making shallow copies of objects. However, there isn’t a lot of strange new implementation under the hood. These syntax features are easily handled by Babel.js and other transpilers.
However, all modern browsers support generators, making it easy for Babel.js to add async functions, or for you to use the “co” library to create the same feature set without a transpiler.
If you’re running Node.js, v4 and beyond support generators and v7.9.5+ supports async functions directly!
While the three features above are available and safe to use, the question of when you can use new features, as they are developed, isn’t always cut and dry.
It was sort of easy to know when a feature was ready to use, in the old days, because of this.
How, then, do you know when you can use a new feature?
It’s not as difficult as it might seem, honestly.
And you can learn all of this through the FREE guide,