JavaScript: New Features of 2023 and Expectations for 2024

The present and the future through (Before/After) examples

JavaScript, the ubiquitous language of the web, continues to evolve with each passing year. In this post, I summarize (from my point of view) some of the significant improvements for this year and we will look ahead to see what’s coming next year.

I hope you find it useful, let’s get started!

JavaScript 2023: The New and Improved

For 2023, five proposals stand out, with each bringing unique additions to the JavaScript language.

1. Symbols as WeakMap keys

Introduced in ECMAScript 2015, WeakMap allows for extending an object with extra properties without worrying about memory leaks. Until now, only objects could serve as keys in a WeakMap. The new feature enables symbols to be used as unique keys in a WeakMap, potentially increasing their usage.

Before:

let objKey = {};
let weakmap = new WeakMap();
weakmap.set(objKey, "I'm an object key!");

console.log(weakmap.get(objKey)); // Output: "I'm an object key!"

In the above example, we created an object objKey to serve as a key in our WeakMap weakmap.

After:

let symbolKey = Symbol("a unique key");
let weakmap = new WeakMap();
weakmap.set(symbolKey, "I'm a symbol key!");

console.log(weakmap.get(symbolKey)); // Output: "I'm a symbol key!"

With the new feature, we’re creating a Symbol symbolKey to serve as a key in our WeakMap weakmap. This way, we can use a unique, non-duplicable value as a key. This is particularly useful when we want to extend an object with additional properties in a way that doesn't interfere with the object itself and is safe from memory leaks.

Already available in recent versions of the main browsers (06/06/2023).

2. Change Array by Copy

This proposal introduces new methods for sorting, reversing, and overwriting data without mutating the array it’s stored in. This allows for more functional programming patterns and consistency in handling arrays and tuples.

Before: Mutating the Array

let array = [3, 2, 1];
array.sort();

console.log(array); // Output: [1, 2, 3]

In the above example, we sorted the array, but the original array was mutated as a result of the sort() operation.

After: Using Change Array by Copy

let array = [3, 2, 1];
let sortedArray = array.sortCopy(); // Proposed method

console.log(array); // Output: [3, 2, 1]
console.log(sortedArray); // Output: [1, 2, 3]

In this example, we’re using the proposed sortCopy() method (the exact method name might differ in the final specification) to sort the array. This new method returns a new sorted array and leaves the original array unmodified.

This feature is part of the functional programming paradigm where data immutability is highly encouraged. By avoiding direct mutations in the original data, we can write safer and more predictable code. It should be noted that this example assumes the existence of a sortCopy() method as described in the proposal, but the future implementation could be different when this feature is officially released.

3. Array find from last

As the name suggests, this feature returns matching elements in an array starting at the end and working back, potentially improving performance or saving the need to write extra code.

Before: Using Array.prototype.find() and Array.prototype.reverse()

let array = [1, 2, 3, 2, 1];
array.reverse();
let foundValue = array.find((element) => element === 2);

console.log(foundValue); // Output: 2

In the above example, we reversed the array and then used find() to search for the first occurrence of the number 2 from the end of the array.

After: Using Array.prototype.findLast()

let array = [1, 2, 3, 2, 1];
let foundValue = array.findLast((element) => element === 2);

console.log(foundValue); // Output: 2

In this example, we’re using the proposed findLast() method (the exact method name might differ in the final specification) to find the first occurrence of the number 2 from the end of the array. This new method allows us to avoid reversing the array and makes our intention clearer.

Already available in recent versions of the main browsers (06/06/2023).

4. Hashbang comments

Standardizing hashbang comments in JavaScript enhances its consistency with other languages. This change could make it easier for JavaScript to participate in the AI and machine learning ecosystem, where Python currently dominates.

Before: Using Hashbang comments

Hashbangs are already being used in JavaScript, especially in Node.js scripts, but their handling was dependent on the host environment. Here’s an example of a Node.js script using a hashbang:

#!/usr/bin/env node
console.log("Hello, world!");

In this example, the hashbang (#!/usr/bin/env node) at the top of the file indicates that the script should be run using Node.js. However, the Node.js host environment is responsible for handling this hashbang and stripping it out before passing the code to the JavaScript engine.

After: Hashbang comments become official

With the standardization of hashbang comments, the JavaScript engine itself will be responsible for handling these comments, ensuring uniform behavior across different host environments. The usage of hashbangs will remain the same:

#!/usr/bin/env node
console.log("Hello, world!");

The difference lies in the underlying handling of these hashbangs, making JavaScript more consistent with other scripting languages and potentially easier to integrate with different ecosystems. Note that this feature is more relevant for server-side JavaScript and doesn’t change much for client-side JavaScript in browsers.

5. findLastIndex

const array = [1, 2, 3, 2, 1];

const lastIndex = array.findLastIndex((x) => x === 2);

console.log(lastIndex); // Output: 3

In this example, findLastIndex is used to find the last occurrence of the number 2 in the array. The function passed to findLastIndex returns true for the number 2 and false for any other number. findLastIndex returns the index of the last array element for which the function returns true.

Already available in recent versions of the main browsers (06/06/2023).

JavaScript 2024: The Road Ahead

While the focus now is on the 2023 features, there are also important proposals for 2024. Although these are still in the early stages of approval, they promise exciting advancements for JavaScript.

6. Temporal API

JavaScript’s existing Date object has been a source of frustration due to its quirky API and design. In response to this, a new API called the Temporal API has been proposed and is in the process of being added to JavaScript. It's designed to be more straightforward and powerful than the Date API.

The Temporal API has reached Stage 3 of the ECMAScript proposal process, which means it’s largely agreed upon but still might have some minor changes before it’s officially added to JavaScript.

Here’s an example of creating a date and getting the current year using the old Date API, and how you'd do the same thing with the proposed Temporal API.

Old way with Date:

let now = new Date();
let currentYear = now.getFullYear();
console.log(currentYear);

New proposed way with Temporal:

let now = Temporal.now.plainDate(); // Returns a PlainDate object representing the current date let currentYear = now.year; // In Temporal, you can get the year directly with .year console.log(currentYear);

7. Pipeline Operator (|>)

The pipeline operator is a syntax sugar for chaining functions in a readable manner. It promises to make functional programming in JavaScript more intuitive and code more readable.

Before using the Pipeline Operator

const double = (x) => x * 2;
const addFive = (x) => x + 5;

const result = addFive(double(10)); // 25

In the old way, we need to nest function calls, which can become complex and hard to read with more functions.

Using the Pipeline operator

const double = (x) => x * 2;
const addFive = (x) => x + 5;

const result = 10 |> double |> addFive; // 25

In this example, we have two functions: double and addFive. The Pipeline Operator (|>) serves as the connector, allowing our data (the number 10) to flow from one function to the next.

8. Error Cause

This proposal adds an optional cause property to Error objects, which can assist in debugging and make developers more productive

Before using the cause property:

try {
  connectToDatabase();
} catch (err) {
  throw new Error("Database connection failed.", { cause: err });
}

Using the cause property:

function buildRSA(p, q) {
  if (!Number.isInteger(p) || !Number.isInteger(q)) {
    throw new Error("RSA key generation requires integer inputs.", {
      cause: { code: "NonInteger", values: [p, q] },
    });
  }
  if (!areCoprime(p, q)) {
    throw new Error("RSA key generation requires two coprime integers.", {
      cause: { code: "NonCoprime", values: [p, q] },
    });
  }
}

In this example, instead of throwing an error with a human-readable message, the cause is provided as structured data for machine analysis. This is useful when the human-readable error messages are inappropriate for machine analysis as they are subject to changes in wording or punctuation that could break any existing analysis written to consume them.

Final thoughts

JavaScript continues to grow and adapt to the needs of developers. The features for 2023 and the proposed enhancements for 2024 indicate a bright future for this dynamic language. As JavaScript continues to mature, we can expect to see more sophisticated and user-friendly features that make coding more efficient and enjoyable.

Note: Recently my boss asked me what language I would recommend for his son, after thinking about it I said JavaScript. It’s not the best-built language and it has too many gotchas but it’s a language that is used for anything and it’s so widespread that learning it is a guarantee. Besides, it continues growing and improving in all its aspects.

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics