11 min read
0%

Modern JavaScript Features

Back to Blog
Modern JavaScript Features

Modern JavaScript Features

JavaScript continues to evolve rapidly. Let’s explore the latest features from ES2024 and beyond, and how to use them effectively in your projects.

Temporal API

Finally, proper date/time handling in JavaScript:

import { Temporal } from "@js-temporal/polyfill";

const now = Temporal.Now.plainDateTimeISO();
const birthday = Temporal.PlainDate.from("1990-05-15");
const age = now.since(birthday).years;

// Duration arithmetic
const meeting = Temporal.PlainDateTime.from("2026-02-15T14:00");
const reminder = meeting.subtract({ hours: 1 });

Records and Tuples

Immutable data structures (Stage 3):

// Records (immutable objects)
const point = #{x: 1, y: 2};
const newPoint = #{...point, z: 3};

// Tuples (immutable arrays)
const rgb = #[255, 0, 0];

Pattern Matching

More expressive conditionals (Stage 2):

const result = match (value) {
  when ({ type: 'success', data }) -> data,
  when ({ type: 'error', message }) -> throw new Error(message),
  when (null) -> 'No data',
  else -> 'Unknown'
};

Pipeline Operator

Compose functions elegantly (Stage 2):

const result = value |> double |> increment |> formatCurrency;

// Instead of:
formatCurrency(increment(double(value)));

Decorators

Metaprogramming for classes (Stage 3):

@logged
class APIClient {
  @memoize
  async fetchData(id) {
    return await fetch(`/api/data/${id}`);
  }
}

function logged(Class) {
  return class extends Class {
    constructor(...args) {
      console.log(`Creating ${Class.name}`);
      super(...args);
    }
  };
}

Array Grouping

Built-in array grouping methods:

const products = [
  { name: "Laptop", category: "Electronics" },
  { name: "Shirt", category: "Clothing" },
  { name: "Phone", category: "Electronics" },
];

const grouped = Object.groupBy(products, (p) => p.category);
// {
//   Electronics: [{...}, {...}],
//   Clothing: [{...}]
// }

Top-Level Await

Use await at module scope:

// module.js
const data = await fetch("/api/config").then((r) => r.json());
export const config = data;

// No need for async IIFE!

Private Fields

True encapsulation in classes:

class Counter {
  #count = 0;

  increment() {
    this.#count++;
  }

  get value() {
    return this.#count;
  }
}

const counter = new Counter();
counter.#count; // SyntaxError

Optional Chaining & Nullish Coalescing

Safe property access and defaults:

const user = {
  profile: {
    name: "John",
  },
};

const email = user?.profile?.email ?? "No email";
const role = user?.role ?? "guest";

Dynamic Import

Load modules on demand:

const shouldLoadChart = true;

if (shouldLoadChart) {
  const { Chart } = await import("./chart.js");
  new Chart("#canvas", data);
}

WeakRef and FinalizationRegistry

Memory-efficient caching:

const cache = new Map();
const registry = new FinalizationRegistry((key) => {
  cache.delete(key);
});

function cacheValue(key, value) {
  const ref = new WeakRef(value);
  cache.set(key, ref);
  registry.register(value, key);
}

Iterator Helpers

Powerful iteration utilities:

const numbers = [1, 2, 3, 4, 5];

numbers
  .values()
  .filter((n) => n % 2 === 0)
  .map((n) => n * 2)
  .take(2)
  .toArray(); // [4, 8]

Async Iteration

Process async data streams:

async function* fetchPages() {
  let page = 1;
  while (page <= 5) {
    const data = await fetch(`/api/page/${page}`);
    yield await data.json();
    page++;
  }
}

for await (const pageData of fetchPages()) {
  console.log(pageData);
}

Conclusion

Modern JavaScript gives us powerful tools for writing cleaner, more expressive code. While some features are still in proposal stages, staying informed helps you write future-proof code.

Keep experimenting and stay curious!


Canvas is not supported in your browser