Upcoming ESNext features - Part 1

Recently I took a look at JavaScript features still in the proposal stage and handpicked the 10 top features that I (a)wait for JavaScript. It would be too long for a single post, so I've sliced it to three posts. Let's check out the first three:

Pipelines

Pipes and pipelines are common in other languages, not just Elm or Hack, but take the UNIX pipe itself. It's really a great tool, and in JavaScript, the closest we got is maybe the chaining pattern, like in jQuery or the Promises.

In chaining, you have to build a chain using the same object or instance, which has to return itself over and over again. With pipelines, you can build powerful data processing chains, using totally independent functions or modules, which has to return a simple value, instead of some mega-structure.

If you're familiar with the componse method of the async library, that may be similar to the pipeline idea. In compose, every provided function receives the return value of the preceding function, until the pipeline ends with a return value.

gist:77dc5632ef13cb9deccdc1dbeda22361#no-pipeline.js

Note that async.compose is async by design, and consecutive functions will wait for each other.

Pipes |>

The Pipeline Operator proposal would like to solve this without dependencies, and the opt-in for async operation too. The following example would look like this using the proposal:

gist:77dc5632ef13cb9deccdc1dbeda22361#pipeline.js

Quick explainer what happens here:

gist:77dc5632ef13cb9deccdc1dbeda22361#pipeline-explainer.js

It's simple so far, although the notation might be a bit confusing at the first time. But let's move on!

The function getName could be async, initiate and wait for an AJAX request to complete. The old async.compose handles that well, but let's see what the new proposal suggests:

gist:77dc5632ef13cb9deccdc1dbeda22361#async-pipeline-problem.js

May look even simpler, but there's a catch! What does await getname means here on Line 9?

gist:77dc5632ef13cb9deccdc1dbeda22361#await-pipeline.js

To solve this confusion, there are two competing proposals on the table right now.

I'll re-write the example again using each of them, so the difference is visible:

gist:77dc5632ef13cb9deccdc1dbeda22361#async-pipeline-proposals.js

The F# proposal separates the await keyword from its async function in the pipeline, so it shows what will be awaited. The Smart Pipeline use a placeholder to tell the pipeline, where to put the return value of the preceding operation. This also offers more versatile use of the placeholder.

Pipelines could be a powerful feature, simplifying flows that were too explicit, or needed a library before. It's currently in stage 1, the decision between the F# and the Smart one has to be made.

They could be even more useful, with the Partial Application feature, so let's take a look at that!

Partial Application

One of my top favorites. If you've tried doing functional programming in JS, or ever used _.partial from lodash, you'll going to love this.

Partially applicating a function means, that you can take a function with more than one arguments, and run it with a number of arguments, that is less than its airity - the number of total arguments it takes. This will give you another function, that you can take and run with the rest of the arguments later. You run or apply it, partially.

Usually, this is achieved using some utility function. A classic example of this is an adding function:

gist:77dc5632ef13cb9deccdc1dbeda22361#partial-application.js

The problem with using utility functions like this, or using .bind() or () => {} is that you have to manage scope, argument order, implementing argument placeholders, or simply put it: rely on a library as a dependency.

The Partial Application proposal would solve this on the native level, plus add some great features too.

Argument placeholders ... ?

The subtitle format is not a suspenseful question :) The proposal has two placeholder tokens, the ? for a single argument and the ... for multiple, more specifically, "rest of the arguments".

gist:77dc5632ef13cb9deccdc1dbeda22361#argument-placeholders.js

This placeholder can be used in any order, or even multiple times:

gist:77dc5632ef13cb9deccdc1dbeda22361#multiple-placeholders.js

The ... - "rest of the arguments" placeholder can be used from the left or right, replacing the first or last part of the argument list:

gist:77dc5632ef13cb9deccdc1dbeda22361#rest-placeholder.js

A quick explainer on how it should work, from the proposal itself.

gist:77dc5632ef13cb9deccdc1dbeda22361#partial-explainer.js

Check out the proposal, for operation details, handling scope, and how it should handle side effects, like changing already applied arguments passed in as variables.

It's currently in stage 1, and has several concerns already

Decorators

This powerful new feature enables us to enhance Objects and Classes further than defineProperty. You can write libraries that can be used later to add extra functionality and behavior to a Class, its methods or even its fields.

Decorators can be used on three declaration points in your code:

  • whole Classes
  • method declarations
  • field declarations, even with setters and getters

See the following example from the current proposal:

gist:77dc5632ef13cb9deccdc1dbeda22361#decorators.js

The example above creates a counter component that updates its text content every time it was clicked. The extra behavior of observing values, binding callbacks to the class instance and the creation of the custom HTML element itself are extracted to Decorators, so they can be re-used on other components - while sticking to a familiar and clean Class structure.

The Decorators proposal is in Stage 2, and this article on its API shows how to implement your own decorators in the (hopefully) near future.

That's it for today, check out the next three features:

  • Bind operator
  • Top-level await
  • Optional Chaining