ESNext: Sort arrays using array.groupBy() and array.groupByToMap()

An ECMAScript Proposal that recently made it to Stage-3 is array grouping. The proposal brings us the array.groupBy() and array.groupByToMap() methods to easily group arrays.

~

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (i.e. 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 Proposal

The proposal offers two methods:

Two methods are offered, groupBy and groupByToMap. The first returns a null-prototype object, which allows ergonomic destructuring and prevents accidental collisions with global Object properties. The second returns a regular Map instance, which allows grouping on complex key types.

With these methods you’ll be able to stop using array.reduce() — a method not everyone likes — to achieve grouping.

~

Examples

Take this array as input:

const array = [1, 2, 3, 4, 5];>

With array.groupBy you can create groups using arbitrary keys. The result is an regular JavaScript object:

array.groupBy((num, index, array) => {
  return num % 2 === 0 ? 'even': 'odd';
});
// =>  { odd: [1, 3, 5], even: [2, 4] }>

The array.groupByToMap method does the same, but it allows you to use complex types (i.e. objects) as keys. The result is a Map:

const odd  = { odd: true };
const even = { even: true };
array.groupByToMap((num, index, array) => {
  return num % 2 === 0 ? even: odd;
});
// =>  Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }>

~

Engine Support

The methods are currently not supported in any JavaScript Engine. A polyfill is available in the core-js library.

~

🔥 Like what you see? Want to stay in the loop? Here's how:

ECMAScript Proposals Overview

Saad Quadri created a handy website that lists all ECMAScript Proposals. On one single page you can get a quick glimpse of all proposals and the current stage they are in.

Great to see that the various stages of the TC39 Development Process themselves —something I always mention in my ever-evolving talk on ESNext— get their own prominent place on the website.

Proposals.es →

You might find this site a little bit handier than the linked-to Markdown files from the official https://tc39.es/

ESNext: Import Assertions (JSON Modules, CSS Modules, …)

Did you know you can import JSON and CSS files just like you import JavaScript Modules? Thanks to Import Assertions, it’s as easy as this:

It’s a regular import statement with an extra assert { "type": … } part added to it. That way you can tell the browser to treat and parse the referenced file to be of a certain type. Once imported you can use the contents further down in your JavaScript code, just like you do with regular ES Module imports.

{
  "appName": "My App"
}
import configData from './config-data.json' assert { type: 'json' };

console.log(configData.appName); // "MyApp"

~

Import Assertions is currently at Stage-3, and is expected to become part of the upcoming ES2022.

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (i.e. 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.

Import Assertions are supported in Chromium 91+. For browsers that don’t support it, you can use the es-module-shims polyfill which provides this functionality (and more nice tings)

~

In the most recent episode of CodePen Radio, just a little after the 10-minute mark, you can see host Chris Coyier demonstrate this (along with importing packages directly from Skypack):

The CSS example Chris shows there uses Lit. In a non-framework environment, add the imported styles using Constructed Stylesheets:

import styles from "./styles.css" assert { type: "css" };
document.adoptedStyleSheets = [...document.adoptedStyleSheets, styles];

💡 Do note that adoptedStyleSheets is only supported in Chromium browsers at the time of writing (CanIUse).

~

If you’re wondering why we can’t simply import those files directly, without the assertions, Axel Rauschmayer has the answer:

Browsers never look at filename extensions, they look at content types. And servers are responsible for providing content types for files.

[…]

With an external server, things are even more risky: If it sends the file with the content type text/javascript, it could execute code inside our app.

~

And oh, Import Assertions can be used with dynamic import(). Pass in the assertion as the second parameter:

const configData = await import('./config-data.json', {
  assert: { type: 'json' },
});
console.log(configData.appName); // "MyApp"

~

A future without a Build System is lurking around the corner, especially when you combine these Import Assertions with a follow-up Evaluator Attributes proposal and Import Maps 🤩

~

~

🔥 Like what you see? Want to stay in the loop? Here's how:

JavaScript Temporal API — A Fix for the Date API

Anyone who has worked with dates and time in JavaScript knows how broken the built-in Date is. In the near future we’ll be able to use Temporal instead, an ECMAScript feature currently at Stage-3

💁‍♂️ Stage-3?

The Technical Committee which is concerned with the standardization of ECMAScript (i.e. 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.

Nathan Sebhastian has a good overview on how it compares to Date, along with some practical examples.

The new Temporal API proposal is designed to solve the problems with the Date API. It brings the following fixes to JavaScript date/time manipulation:

  • Creating and dealing only with immutable Temporal objects
  • Straightforward API for date and time computations
  • Support for all timezones
  • Strict date parsing from ISO-8601 format
  • Support for non-Gregorian calendars

JavaScript Temporal API — A Fix for the Date API →

What’s new in ES2021

With the January meeting of TC39 behind us, the Stage-4 features that will make it into ES2021 have been selected.

💁‍♂️ Stage-4?

The Technical Committee which is concerned with the standardization of ECMAScript (i.e. 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.

The following features will be part of ES2021, which will be formalised mid-2021:

Apart from the linked-to posts above, Pawel Grzybek has done a writeup on all features. Additionally you can check all posts tagged es2021 on the V8 blog.

☝️ Note that you can use (most of) these features today already, as browsers start rolling them out (unflagged) when they hit Stage-3. So no, you don’t have to wait until mid-2021 to start using them.

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 (i.e. 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: Proposals to look forward to (ESNEXT Conf)

Happening right now is ESNEXT Conf a fully remote conference exploring the future of JavaScript and the web. When I saw the CFP float by, it sounded like a perfect match for my talk “ESNext: Proposals to look forward to”. Thankfully the organisers – Fred and Drew from Pika – also felt that ways and the put me in the line-up.

With the yearly ECMAScript releases (ES2015..ES2020) of a lot of things have changed in JavaScript-land, and there’s even more to come. This talk takes a look at a few of the newest (ES2020) and some of the upcoming ECMAScript features, which (hopefully) will become part of the ECMAScript Language Specification in the near future.

~

Talk Slides

The slides are up on slidr.io, and also embedded below:

~

Talk Outline

  • ECMAScript History and Timeline
  • TC39: Info on TC39, what they do, and how they work.
  • ESNext Proposal: Field Declarations
  • ES2020 Feature: Optional Chaining
  • ES2020 Feature: Null Coalescing
  • ESNext Proposal: Logical Assignment
  • ES2020 Feature: Dynamic Imports
  • ESNext Proposal: Decimal
  • ESNext Proposal: Cancellation API (+ Mention of AbortController)
  • ESNext Proposal: Declarations In Conditionals
  • ES2019 Feature: Object.fromEntries()
  • ESNext Proposal: Slice Notation
  • ESNext Proposal: Pattern Matching
  • Fin.

~

Talk Video

Once the video has been released, I’ll update this post to include it. Here it is:

~

Thanks to the organisers for having me, and thanks to the attendees for coming to see me. I hope you all had fun attending this talk. I know I had making it (and whilst bringing it forward). A shame we couldn’t meet in person though, perhaps at a next edition 😉

💁‍♂️ If you are a conference or meetup organiser, don’t hesitate to contact me to come speak at your event.

ESNext: Proposals to look forward to (JS VidCon / JavaScript Remote Conf)

The past few days I’ve been attending some virtual conferences. At JS VidCon and JavaScript Remote Conf I also joined as a speaker, to bring forward my ever-evolving talk “ESNext: Proposals to look forward to”

With the yearly ECMAScript releases (ES2015..ES2020) of a lot of things have changed in JavaScript-land, and there’s even more to come. This talk takes a look at a few of the newest (ES2020) and some of the upcoming ECMAScript features, which (hopefully) will become part of the ECMAScript Language Specification in the near future.

The slides are up on slidr.io, and also embedded below:

Talk Outline:

  • JavaScript Yellow: How to get JavaScript Yellow on your website (a plea to using the right tool for the right job)
  • TC39: Info on TC39, what they do, and how they work.
  • ESNext Proposal: Field Declarations
  • ESNext Proposal: Pipeline Operator
  • ES2020 Feature: Optional Chaining
  • ES2020 Feature: Null Coalescing
  • ESNext Proposal: Logical Assignment
  • ES2020 Feature: Dynamic Imports
  • ESNext Proposal: Export Default From
  • ESNext Proposal: Decimal
  • ESNext Proposal: Cancellation API (+ Mention of AbortController)
  • ESNext Proposal: Declarations In Conditionals
  • ESNext Proposal: Slice Notation
  • ES2019 Feature: Object.fromEntries()
  • ESNext Proposal: Pattern Matching
  • Fin.

Thanks to the organisers for having me, and thanks to the attendees for coming to see me. I hope you all had fun attending this talk. I know I had making it (and whilst bringing it forward). A shame we couldn’t meet in person though, perhaps at a next edition 😉

💁‍♂️ If you are a conference or meetup organiser, don’t hesitate to contact me to come speak at your event.

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 (i.e. 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 (i.e. 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.