ESNext: Declarations in Conditionals (Stage-1)

An ECMAScript Language Feature that I’m looking forward to is Declarations in Conditionals. It adds the capability to declare variables inside conditional statements. Let’s take a look …

~

Setting the Scene

Say you want to iterate over an array which might be tucked away inside an object. To do so, you’d most likely first check for that variable’s existence using a simple if

if (user.meta.interests) {
    for (let interest of user.meta.interests) {
        // …
    }
}

As we’re now typing user.meta.interests twice in our code you might declare an intermediary variable, and use that further down in your code:

let interests = user.meta.interests;
if (interests) {
    for (let interest of interests) {
        // …
    }
}

But now you have a nasty side-effect: you’re loitering the scope with this extra interests variable. This is quite useless, as you’re only using it inside the if statement.

💁‍♂️ To make it totally failsafe, you might also want to add some Optional Chaining in there and check if interests is iterable, but that’s beyond the scope of this post.

~

Hello “Declarations in Conditionals”

With the “Declarations in Conditionals” proposal we can keep this extra interests variable, yet without loitering the outer scope. We do this by declaring the variable directly inside the conditional (e.g. if statement), like so:

if (let interests = user.meta.interests) {
    for (let interest of interests) {
        // …
    }
}

⚠️ Note that this is an assignment right there, not an equality check!

With that one line the interests variable:

  1. will be declared
  2. will have a value assigned to it
  3. will be checked for being falsy or not

Scope-wise the interests variable will have its scope limited local to the conditional (e.g. only visible inside the if).

The proposal limits declarations to use either const or let; declarations in conditionals with var are currently not allowed.

💡 You might not 100% realize it, but you’re already doing this kind of thing when using a for loop. Inside its initialization part (e.g. its first part) you are also declaring variables.

for (let i = 0; i < 5; i++) {
  console.log(i);
}

☝️ Did you know that you can declare more than one variable there, separated by a comma? In the example below I declare an extra variable len right after declaring i:

const cars = ['Ford', 'Mercedes', 'BMW'];

for (let i = 0, len = cars.length; i < len; i++) {
  console.log(cars[i]);
}

🤔 What about the scope of len you might ask? Variables declared using let are scoped to the statement (e.g. local to the loop). Variables declared using var get hoisted. And oh, it’s not allowed to declare variables using const here.

~

So, when can we use this?

The proposal is currently Stage-1, so it still has a long way to go before it can become an official part of the standard — if it ever will be.

💁‍♂️ Stage-1?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-1 is the Proposal stage. It signals that the committee is showing interest in the proposal and that it is seeking further investigation on how to tackle it. At this stage the proposal is subject to heavy changes. It is only when a proposal reaches Stage 4 that it is ready to become part of the ECMAScript Specification.

As it’s still Stage-1, it can change quite a lot before it to be finished. And I’m quite sure it will change, as right now:

  • It only allows declaring one variable.
  • It only checks for values being falsy or not.

These two feature are currently listed under “Future Work” of the proposal, and it looks like this:

if (let x = 1, y = 2; x || y) {
    // …
}

Must say I’m pretty curious how this one will evolve, as I’m already quite excited about it: it’s one of those small additions that will have a pretty big impact on how I write my code.

If you have an addition to this proposal, feel free to join the discussion in the Declarations in Conditionals GitHub repository.

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

ESNext: Logical Assignment Operators (||=, ??=, &&=)

Update 2020.07.21:

This proposal made it into Stage-4 and will officially be part of ES2021 🥳

💁‍♂️ Stage-4?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-4 is the Finished Stage and indicates that the proposal is ready to become part of the ECMAScript Specification.

A new ECMAScript Proposal that I’m looking forward to is Logical Assignment Operators. In short it combines Logical Operators (||, &&, and ??) with Assignment Expressions (=).

// "Or Or Equals" (or, the Mallet operator)
a ||= b;

// "And And Equals"
a &&= b;

// "QQ Equals"
a ??= b;

Basically these operators translate to these actions being performed:

  • ||= will only assign the value of b into a if a is falsy (false, 0, null, etc.).
  • &&= will only assign the value of b into a if a is truthy (true, 1, {}, etc.).
  • ??= will only assign the value of b into a if a is null or undefined.

🤔 Not familiar with that ?? you see there? It’s the Nullish Coalescing Operator which is part of ES2020 and it’s awesome!

~

These operators will change the way you code, see this before/after example:

// Without Logical Assignment
name = name ?? 'stranger';

// With Logical Assignment
name ??= 'stranger'

Using Logical Assignment Operators will save you to writing an if statement. Additionally it can save a setter execution.

let name = 'bramus';

// Without Logical Assignment: the value of name will *always* be set to (here: to its own value), even though name is not nullish
name = name ?? 'stranger';

// With Logical Assignment: name won't be reassigned as name is not nullish
name ??= 'stranger'

~

The Logical Assignment Operators proposal is currently Stage-3.

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.

Since it’s Stage-3, we can expect things to look good implementation-wise, which it totally is:

  • Babel: The “Mallet Operator Transformer” got added a long time ago (back when it was still called “6to5”). Nowadays you should use the @babel/plugin-proposal-logical-assignment-operators plugin.
  • Chrome/V8: The feature got added two days ago and will get shipped with V8 v8.4 behind the flag --harmony-logical-assignment
  • Firefox/SpiderMonkey: Version 77 should support it, but I couldn’t get it to work in Firefox Developer Edition (77.0b2). Firefox Nightly (78.0a1) works fine.
  • Safari/JavaScriptCore: Logical Assignment Operators shipped with Safari Technology Preview 105

I don’t expect this proposal to change at all anymore and can see it advancing to Stage-4 at the one of the next TC39 meetings. That way this proposal will most likely become part of ES2021.

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

ESNext: Get localized language, currency, and region names with Intl.DisplayNames

An ECMAScript Internationalization API Feature that currently is in Stage-3 and that has already landed in V8 version 8.1 is Intl.DisplayNames. It’s a way to get localized display names for languages, scripts, regions and others.

🤔 Note that this proposal is part of ECMA-402 (the ECMAScript Internationalization API Specification) and not ECMA-262 (The ECMAScript Language Specification). Therefore this proposal will not be part of the yearly "ES20XX”, as that term only applies to ECMA-262.

To advance proposals in ECMA-402, TC39 uses the same 5-stage-process as they use in ECMA-262.

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.

The idea is that you as a developer should not build your own list of localized strings for languages, regions, etc. but that the JavaScript runtime should provide if for you:

Translation of languages, regions or script display names requires large amount of data to transmit on the network, which is already available in most browsers. The Intl.DisplayNames API will allow web developers to shrink the size of their HTML and/or ECMA script code without the need to include the human readable form of display names and therefore reduce the download size to decrease latency.

💁‍♂️ Another nice API exposed on Intl is Intl.RelativeTimeFormat which allows you to relatively format time in JavaScript.

~

Examples

// Get display names of region in English
const regionNames = new Intl.DisplayNames(['en'], {type: 'region'});
console.log(regionNames.of('419')); // "Latin America"
console.log(regionNames.of('BZ')); // "Belize"
console.log(regionNames.of('US')); // "United States"
console.log(regionNames.of('BA')); // "Bosnia & Herzegovina"
console.log(regionNames.of('MM')); // "Myanmar (Burma)"

// Get display names of language in Traditional Chinese
const languageNames = new Intl.DisplayNames(['zh-Hant'], {type: 'language'});
console.log(languageNames.of('fr')); // "法文"
console.log(languageNames.of('zh')); // "中文"
console.log(languageNames.of('de')); // "德文"

// Get display names of script in Traditional Chinese
const scriptNames = new Intl.DisplayNames(['zh-Hant'], {type: 'script'});
console.log(scriptNames.of('Latn')); // "拉丁文"
console.log(scriptNames.of('Arab')); // "阿拉伯文"
console.log(scriptNames.of('Kana')); // "片假名"

// Get display names of currency code in English
const currencyNames = new Intl.DisplayNames(['en'], {type: 'currency'});
console.log(currencyNames.of('USD')); // "US Dollar"
console.log(currencyNames.of('EUR')); // "Euro"
console.log(currencyNames.of('TWD')); // "New Taiwan Dollar"
console.log(currencyNames.of('CNY')); // "Chinese Yuan"

~

Syntax

The constructor takes two arguments: locales and options. Both are optional:

new Intl.DisplayNames([locales[, options]]);

Once you have a Intl.DisplayNames instance, you use its .of method to request a localised string

Intl.DisplayNames.prototype.of(code);

~

Constructor Arguments

locales

The locales argument is a BCP 47 language tag which identifies the locale to use. The main parts, amongst others, of a BCP 47 language tag are language, script, and region

  • The language part is a 2/3 character long ISO 639-1 code
  • The (optional) script part is a 4 character long ISO 15924 code
  • The (optional) region part is a 2 alpha or 3 digit long ISO 3166-1 code

When more than one part is present, they are separated by a dash (-)

Examples:

  • "nl": Dutch (language).
  • "nl-BE": Dutch as used in Belgium (language + region).
  • "zh-Hans-CN": Chinese written in simplified characters as used in China (language + script + region).

When locales is omitted, it will default to the language-setting of the browser/system.

options

The options object allows you to tweak how Intl.DisplayNames behaves. It has the following properties:

  • localeMatcher

    The locale matching algorithm to use. Possible values are "lookup" and "best fit" (default)

  • style

    The length of the output message, e.g. "English (United States)" vs. "English (US)". Possible values are "long" (default) and "short", or “narrow” (which mostly yields the same result as "short", depending on the language)

  • type

    What you want to display. Possible values are "region", "script", "language", or "currency".

~

Intl.DisplayNames.prototype.of Arguments

code

Depending on the type you passed into the constructor, you pass in a different value for code:

~

JS/Browser Support

Intl.DisplayNames already shipped in V8 v8.1 (included in the upcoming Chrome 81) and will be available in Node 14. Other JS runtimes / browsers don’t support it at the time of writing.

~

The future: More types to come!

When looking at the open issues listed on the proposal’s repository you can see that there’s more to come in a future version of Intl.DisplayNames: support for units, timezones, emoji names, date parts (such as months, weekdays, etc).

For this first release the scope was limited to supporting the types "region", "script", "language", and "currency".

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

ESNext: Replace all occurrences of a piece of text in a string with String.prototype.replaceAll

UPDATE June 2020: This feature has advanced to Stage-4 and will be part of the ES2021 Specification! 🎉

An ECMAScript Language feature that’s currently in Stage-3 is String.prototype.replaceAll, a handy way to replace all instances of a piece of text in a string.

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.

~

The Problem

If you ever needed to replace a piece of text in a string you most likely will have used String.prototype.replace:

'the quick brown fox jumps over the lazy dog'.replace('a', '_')
// ~> "the quick brown fox jumps over the l_zy dog"

There’s one somewhat counterintuitive issue with it though: it only replaces the first match it finds:

'the quick brown fox jumps over the lazy dog'.replace('o', '_')
// ~> "the quick br_wn fox jumps over the lazy dog"

One of the workarounds we can use today is to use a global regular expression (e.g. a RegEx with the g flag):

'the quick brown fox jumps over the lazy dog'.replace(/o/g, '_')
// ~> "the quick br_wn f_x jumps _ver the lazy d_g"

~

The Solution

The String.prototype.replaceAll proposal offers us a non-hacky solution, right in the JavaScript language:

'the quick brown fox jumps over the lazy dog'.replaceAll('o', '_')
// ~> "the quick br_wn f_x jumps _ver the lazy d_g"

Its method signature is exactly the same as String.prototype.replace‘s:

String.prototype.replaceAll(searchValue, replaceValue)

Implementation-wise it differs in only two ways from String.prototype.replace:

  1. When given a string as its searchValue: replaceAll will replace all occurrences, whereas replace will only replace the first — hence why it is being proposed in the first place.
  2. When given a non-global regular expression (e.g. a RegEx without the g flag) as its searchValue: replaceAll will throw an exception as the word replaceAll implies to “replace all” but the lack of the g flag implies exactly the opposite — Computer says no.

~

Browser Support

Although the feature is Stage-3 already, it’s not enabled in browsers yet. To test this feature:

  • In Chrome: Enable #enable-javascript-harmony in chrome://flags/
  • In Firefox: N/A
  • In Safari: Enabled in Safari Technology Preview Release 97

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

ESNext: Relatively format time with Intl.RelativeTimeFormat

A proposal to the ECMAScript Internationalization API Specification (ECMA-402) that just moved to Stage-4, is Intl.RelativeTimeFormat. It’s a way to format time in a relative manner – e.g. “10 minutes ago” or “in 3 quarters” – while also taking a language into account.

🤔 Note that this proposal is part of ECMA-402 (the ECMAScript Internationalization API Specification) and not ECMA-262 (The ECMAScript Language Specification). Therefore this proposal will not be part of the yearly "ES20XX”, as that term only applies to ECMA-262.

To advance proposals in ECMA-402, TC39 uses the same 5-stage-process as they use in ECMA-262.

💁‍♂️ Stage-4?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-4 is the Finished Stage and indicates that the proposal is ready to become part of the ECMAScript Specification.

const rtf_en = new Intl.RelativeTimeFormat('en');

console.log(rtf_en.format(-1, 'day')); // ~> 1 day ago
console.log(rtf_en.format(30, 'seconds')); // ~> in 30 seconds
const rtf_nl = new Intl.RelativeTimeFormat('nl-BE', {
    localeMatcher: 'best fit', // other values: 'lookup'
    numeric: 'auto', // other values: 'always'
    style: 'short', // other values: 'long' or 'narrow'
});

console.log(rtf_nl.format(-1, 'day')); // ~> gisteren
console.log(rtf_nl.format(30, 'seconds')); // ~> over 30 sec.

~

Syntax

The constructor takes two arguments: locales and options. Both are optional:

new Intl.RelativeTimeFormat([locales[, options]]);

Possible units to use while formatting are "year", "quarter", "month", "week", "day", "hour", "minute", and "second".

~

Constructor Arguments

locales

The locales argument is a BCP 47 language tag which identifies the locale to use. The main parts, amongst others, of a BCP 47 language tag are language, script, and region

  • The language part is a 2/3 character long ISO 639-1 code
  • The (optional) script part is a 4 character long ISO 15924 code
  • The (optional) region part is a 2 alpha or 3 digit long ISO 3166-1 code

When more than one part is present, they are separated by a dash (-)

Examples:

  • "nl": Dutch (language).
  • "nl-BE": Dutch as used in Belgium (language + region).
  • "zh-Hans-CN": Chinese written in simplified characters as used in China (language + script + region).

When locale is omitted, it will default to the language-setting of the browser/system.

options

The options object allows you to tweak how Intl.RelativeTimeFormat behaves. It has the following properties:

  • localeMatcher

    The locale matching algorithm to use. Possible values are "lookup" and "best fit" (default)

  • numeric

    The format of output message. Possible values are "always" (always include a number in the output, default) or "auto" (which allows output such as “in 1 day” to be rewritten in the more natural "tomorrow")

  • style

    The length of the output message, e.g. "in 1 month" vs. "in 1 mo.". Possible values are "long" (default), "short", or “narrow” (which mostly yields the same result as "short", depending on the language)

~

Extracting all parts with formatToParts

If you don’t want a string to be returned, you can use formatToParts() to get an object describing all parts:

const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });

// Format relative time using the day unit.
rtf.formatToParts(-1, "day");
// > [{ type: "literal", value: "yesterday"}]

rtf.formatToParts(100, "day");
// > [{ type: "literal", value: "in " }, { type: "integer", value: "100", unit: "day" }, { type: "literal", value: " days" }]

~

JS/Browser Support

Intl.RelativeTimeFormat shipped in V8 v7.1.179 (included Chrome 71) and Firefox 65.

Polyfills are available:

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

ESNext: JavaScript “Nullish Coalescing Operator”

UPDATE December 2019: This feature has now advanced to Stage-4 and will be part of the ES2020 Specification! 🎉

One of my favorite ECMAScript Proposals is the “Optional Chaining Operator”. Another proposal that forms great duo with it is the “Nullish Coalescing Operator” (sometimes also referred to as “Nullary Coalescing Operator”).

Both proposals still are Stage-1, but don’t let that stop us from taking a peek into it right now.

💁‍♂️ Stage-1?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-1 is the Proposal stage. It signals that the committee is showing interest in the proposal and that it is seeking further investigation on how to tackle it. At this stage the proposal is subject to heavy changes. It is only when a proposal reaches Stage 4 that it is ready to become part of the ECMAScript Specification.

~

The problem

As explained in the “Optional Chaining Operator” post we can get properties of an object in a fail safe way using Short-Circuit Logic or by using the proposed Optional Chaining operator (?.) in the nearby future:

// Today: Extract firstName using Short-Circuit Logic
const firstName = message.body && message.body.user && message.body.user.firstName;
// Near future: Extract firstName using the Optional Chaining Operator
const firstName = message.body?.user?.firstName;

A common technique used is to add a default fallback value using the logical OR operator (||):

const firstName = message.body?.user?.firstName || 'Stranger';

Whilst this works fine, there is one problem with falsy values: when the left hand side of the OR expression evaluates to falsy (e.g. null, undefined, false, 0, empty string, …), the right hand side of the expression will be used. For null and undefined that’s not a problem, but it is for false, 0, empty string, etc.:

const message = {
    settings: {
        animationDuration: 0,
        showSplashScreen: false
    },
};

const showSplashScreen = message.settings?.showSplashScreen || true;
// --> true 🚫

The result here is true (the fallback), even though message.settings.showSplashScreen was defined to be false.

~

The solution

The proposed Nullish Coalescing Operator ?? is intended to provide a solution to this problem. It serves as an equality check against nullary values (e.g.
null or undefined). Whenever the expression to the left of the ?? operator evaluates to either undefined or null, the value defined to the right will be returned.

Combined with the Optional Chaining Operator, our code snipped can be fixed like this:

const message = {
    settings: {
        animationDuration: 0,
        showSplashScreen: false
    },
};

const showSplashScreen = message.settings?.showSplashScreen ?? true;
// --> false 🎉

Small change, big impact 🙂

~

So, when can we us this?

You can use the Nullish Coalescing Operator today already thanks to Babel’s plugin-proposal-nullish-coalescing-operator plugin (for use with Babel 7).

Do note that the proposal still Stage-1 (soon Stage-2 by the looks of it) and might still change in the future.

~

In short

💻 The examples embedded in this post are part of a talk on ESNext named “What’s next
 for JavaScript?”, which I recently gave at a Fronteers België meetup and Frontend United 2018 (Utrecht). You can check the slides / a recording out here. I’m available for bringing this talk at your meetup/conference.

👋 This post also got published on Medium. If you like it, please give it some love a clap over there.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

JavaScript: What’s new in ECMAScript 2018 (ES2018)?

👋 This post also got published on Medium. If you like it, please give it some love a clap over there.

At the latest TC39 meeting the new features that will make it into the “ECMAScript® 2018 Language Specification” (ES2018) have been selected. All proposals that have reached stage-4 since the consolidation of ES2017 got selected. This post gives one a quick look at the features that made it into ES2018.

💁‍♂️ Stage-4?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-4 is the Finished Stage and indicates that the proposal is ready to become part of the ECMAScript Specification.

~

Rest/Spread Properties

When destructuring, Rest/Spread Properties allow you to collect the remaining properties of an object into a new object. Think of it as a magic magnet attracting all leftovers.

I use this one myself a lot, especially in a React (Native) context where I pluck certain values from this.props for internal use, and then forward all other props to the returned child component.

Additionally, if you turn your thinking-logic around a bit, Rest/Spread Properties provide you with a good way to remove a property from an object in an immutable way.

~

Asynchronous Iteration

With Asynchronous Iteration we get asynchronous iterators and asynchronous iterables. Asynchronous iterators just like regular iterators, except their next() method returns a promise for a { value, done } pair. To consume asynchronous iterables, we can now use the await keyword with for … of loops.

~

Promise.prototype.finally()

Promise.prototype.finally() finalizes the whole promises implementation, allowing you to register a callback to be invoked when a promise is settled (either fulfilled, or rejected).

A typical use case is to hide a spinner after a fetch() request: instead of duplicating the logic inside the last .then() and .catch(), one can now place it inside .finally()

~

RegExp related features

In total 4 RegExp related proposals made it into ES2018:

I especially digg the “RegExp named capture groups” feature, as it improves readability:

More info on these features can be found at Mathias Bynens – one of the driving forces behind these proposals – his blog: ECMAScript regular expressions are getting better!

~

Other new Features

To top it off a tweak to template literals landed: when using tagged template literals the restriction on escape sequences are removed, thus allowing things like \xerxes. Before this tweak an error would be thrown because \x is the start of a hex escape with erxes not being a valid hex value.

Tagged template literal?

💁‍♂️ As per MDN: If there is an expression preceding the template literal, the template string is called a “tagged template literal”. In that case, the tag expression (usually a function) gets called with the processed template literal, which you can then manipulate before outputting.

~

What now?

Do note that not all these features are readily available in all browsers. Meaning that they’re Stage-4 means that they are finished, and that browser vendors should implement them (some already have, others are in the process).

As for the future, I’m already looking forward at what’s next to come for JavaScript. Things like the Optional Chaining Operator already get me very excited 🙂

💻 The examples embedded in this post are part of a talk on ESNext named “What’s next
 for JavaScript?”, which I recently gave at a Fronteers België meetup. I’m currently still in the process of preparing the slides for publication. I’m available for bringing this talk at your meetup/conference.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

ESNext: Dynamically import ES modules with “dynamic import()

UPDATE June 2019: This feature has now advanced to Stage-4 and will be part of the ES2020 Specification! 🎉

One of the recent ECMAScript proposals that landed in Chrome 63 is dynamic import():

Dynamic import() introduces a new function-like form of import, which allows one to import on demand. It returns a promise for the module namespace object of the requested module, which is created after fetching, instantiating, and evaluating all of the module’s dependencies, as well as the module itself.

Say you have a lightbox or dialogbox. You could offload its importing to the very moment it is needed:

button.addEventListener('click', async (event) => {
    try {
        const dialogBox = await import('./dialogBox.mjs');
        dialogBox.open(…);
    } catch (error) {
        // …
    }
});

Note that we’re using await here, as it’s better than the typical promise code which uses .then().

The proposal is currently Stage-3

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-3 is the Candidate Stage where the feature is considered complete and only critical changes will happen based on implementation experience. If all goes well the proposal will advance to Stage 4 without any changes, after which it will to become part of the ECMAScript Specification.

ESNext Proposal: The Pipeline Operator

The pipeline operator is essentially a useful syntactic sugar on a function call with a single argument. In other words, sqrt(64) is equivalent to 64 |> sqrt.

This allows for greater readability when chaining several functions together.

With the Pipeline Operator, one could rewrite this …

let result = exclaim(capitalize(doubleSay("hello")));

… to this (think Unix pipes!):

let result = "hello"
  |> doubleSay
  |> capitalize
  |> exclaim;

The proposal also caters for functions with multiple arguments with arrow functions or partial application.

The proposal is currently Stage 1

💁‍♂️ Stage-1?

The Technical Committee which is concerned with the standardization of ECMAScript (e.g. TC39) has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature.

Stage-1 is the Proposal stage. It signals that the committee is showing interest in the proposal and that it is seeking further investigation on how to tackle it. At this stage the proposal is subject to heavy changes. It is only when a proposal reaches Stage 4 that it is ready to become part of the ECMAScript Specification.

ESNext Proposal: The Pipeline Operator →

Related: Whilst this proposed operator only gets me lightly excited, one that does get me very excited is The Null Propagation Operator. You should definitely check it out.

What’s new in JavaScript? ES2017 Language Features

The ECMAScript 2017 Language Specification – the 8th edition of the spec – was officially released at the end of June by TC39.

💁‍♂️ ICYWW: Should we say ES2017 or ES8?

→ Say ES2017. Back in the day ES6 was (and still is) used a lot to refer to ES2015, but one should be referring to the standard using the year references (or refer to a language feature using its name)

One of the top additions – which I’ve been using for quite a while now thanks to babel-polyfill and its included core-js – is Object.entries()/Object.values(), as they have rather big effect on the way I write my code.

const obj = { x: 'xxx', y: 1 };
Object.values(obj); // ['xxx', 1]

const obj = { x: 'xxx’, y: 1 };
Object.entries(obj); // [[’x’, 'xxx’], [’y’, 1]]

As it’s an array, one can easily append a .forEach(…) to each one of these beauties to get going … And don’t forget about map/reduce/filter either 😉

Async functions is also at the top of my list of influential features:

function fetchTextByPromise() {
  return new Promise(resolve => { 
    setTimeout(() => { 
      resolve("ES2017");
    }, 2000);
  });
}

async function sayHello() { 
  const externalFetchedText = await fetchTextByPromise();
  console.log(`Hello, ${externalFetchedText}`); // Hello, ES2017
}
sayHello();

Furthermore some new string padding functions, Object.getOwnPropertyDescriptors(obj), “Trailing commas in function parameter lists and calls”, and “Shared memory and atomics” has been added.

ES8 was Released and here are its Main New Features →
ECMAScript 2017 Language Specification (PDF) →

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)