Back to Home

JavaScript ES2024: New Features You Should Know

4 min read

Discover the latest JavaScript features in ES2024. From new array methods to improved async patterns, learn what's new in the JavaScript ecosystem.

JavaScript ES2024: New Features You Should Know

The JavaScript language continues to evolve with exciting new features in ES2024 (ES15). This article explores the most significant additions and how they can improve your development workflow.

New Array Methods

Array.prototype.with()

Create a new array with a single element changed:

const numbers = [1, 2, 3, 4, 5];
const updated = numbers.with(2, 10);
console.log(updated); // [1, 2, 10, 4, 5]
console.log(numbers); // [1, 2, 3, 4, 5] (original unchanged)

Array.prototype.toReversed()

Returns a new array with elements in reverse order:

const original = [1, 2, 3, 4, 5];
const reversed = original.toReversed();
console.log(reversed); // [5, 4, 3, 2, 1]
console.log(original); // [1, 2, 3, 4, 5] (unchanged)

Array.prototype.toSorted()

Create a new sorted array without mutating the original:

const names = ['Charlie', 'Alice', 'Bob'];
const sorted = names.toSorted();
console.log(sorted); // ['Alice', 'Bob', 'Charlie']
console.log(names);  // ['Charlie', 'Alice', 'Bob'] (unchanged)

Array.prototype.toSpliced()

Non-mutating version of splice():

const fruits = ['apple', 'banana', 'cherry', 'date'];
const modified = fruits.toSpliced(1, 2, 'blueberry', 'coconut');
console.log(modified); // ['apple', 'blueberry', 'coconut', 'date']
console.log(fruits);   // ['apple', 'banana', 'cherry', 'date'] (unchanged)

Enhanced String Methods

String.prototype.isWellFormed()

Check if a string contains well-formed Unicode:

const wellFormed = "Hello 👋";
const malformed = "Hello \uD800"; // Lone surrogate

console.log(wellFormed.isWellFormed()); // true
console.log(malformed.isWellFormed());  // false

String.prototype.toWellFormed()

Convert to well-formed Unicode string:

const malformed = "Hello \uD800 World";
const fixed = malformed.toWellFormed();
console.log(fixed); // "Hello � World" (with replacement character)

Object Grouping

Object.groupBy()

Group array elements by a key function:

const people = [
  { name: 'Alice', age: 25, department: 'Engineering' },
  { name: 'Bob', age: 30, department: 'Marketing' },
  { name: 'Charlie', age: 35, department: 'Engineering' },
  { name: 'Diana', age: 28, department: 'Marketing' }
];

const byDepartment = Object.groupBy(people, person => person.department);
console.log(byDepartment);
// {
//   Engineering: [
//     { name: 'Alice', age: 25, department: 'Engineering' },
//     { name: 'Charlie', age: 35, department: 'Engineering' }
//   ],
//   Marketing: [
//     { name: 'Bob', age: 30, department: 'Marketing' },
//     { name: 'Diana', age: 28, department: 'Marketing' }
//   ]
// }

Map.groupBy()

Similar to Object.groupBy() but returns a Map:

const byAgeGroup = Map.groupBy(people, person => {
  return person.age < 30 ? 'young' : 'experienced';
});
console.log(byAgeGroup);
// Map {
//   'young' => [
//     { name: 'Alice', age: 25, department: 'Engineering' },
//     { name: 'Diana', age: 28, department: 'Marketing' }
//   ],
//   'experienced' => [
//     { name: 'Bob', age: 30, department: 'Marketing' },
//     { name: 'Charlie', age: 35, department: 'Engineering' }
//   ]
// }

Promise.withResolvers()

A new static method that returns an object with a promise and its resolve/reject functions:

const { promise, resolve, reject } = Promise.withResolvers();

// Use the promise
promise.then(value => console.log('Resolved:', value));

// Resolve from elsewhere
setTimeout(() => resolve('Hello from the future!'), 1000);

This is particularly useful for creating promises that need to be resolved from external contexts.

Atomics.waitAsync()

Non-blocking version of Atomics.wait():

const sharedBuffer = new SharedArrayBuffer(1024);
const sharedArray = new Int32Array(sharedBuffer);

// Non-blocking wait
const result = Atomics.waitAsync(sharedArray, 0, 0);
if (result.async) {
  result.value.then(outcome => {
    console.log('Wait completed:', outcome);
  });
}

Regular Expression v Flag

Enhanced Unicode support in regular expressions:

// Unicode property escapes in character classes
const regex = /[\p{Script=Latin}&&\p{Letter}]/v;
console.log(regex.test('a')); // true
console.log(regex.test('α')); // false

// String literals in character classes
const emojiRegex = /[\q{👨‍💻|👩‍💻|🧑‍💻}]/v;
console.log(emojiRegex.test('👨‍💻')); // true

ArrayBuffer Transfer

Transfer ownership of ArrayBuffer between contexts:

const buffer = new ArrayBuffer(1024);
const view = new Uint8Array(buffer);
view[0] = 42;

// Transfer the buffer (becomes detached in current context)
const transferred = buffer.transfer();
console.log(buffer.byteLength); // 0 (detached)
console.log(transferred.byteLength); // 1024

Best Practices

  1. Use Non-Mutating Array Methods: Prefer toSorted(), toReversed(), etc. for immutable operations
  2. Leverage Object.groupBy(): Simplify data transformation and grouping operations
  3. Check Unicode Well-Formedness: Use isWellFormed() when dealing with user-generated content
  4. Adopt Promise.withResolvers(): For complex promise orchestration scenarios

Browser Support

These features are rolling out across modern browsers:

  • Chrome 117+ (most features)
  • Firefox 118+ (most features)
  • Safari 17+ (most features)

Always check current compatibility tables and consider polyfills for production use.

Conclusion

ES2024 brings practical improvements to JavaScript with a focus on immutability, better Unicode handling, and enhanced developer experience. These features make JavaScript code more predictable and easier to reason about, especially in functional programming paradigms.