ECMAScript 2023 (ES14) introduced several practical additions to the JavaScript language that are fully supported in all modern browsers and in Node.js 20+ — making them usable in WordPress JavaScript that targets modern browsers via a build step, in wp-scripts projects, and in Node.js tooling scripts. The most useful additions for WordPress developers: Array.prototype.findLast() and Array.prototype.findLastIndex() search an array from the end for the first element matching a predicate — useful for finding the most recent item in a sorted array without reversing the array first (reversing creates a copy, which is wasteful for large arrays). Array.prototype.toReversed(), Array.prototype.toSorted(), and Array.prototype.toSpliced() are the immutable versions of reverse(), sort(), and splice() — they return a new array instead of mutating the original, enabling functional programming patterns without needing to manually copy the array before mutating it. These methods pair naturally with Proxy-based reactive stores (mutation of the original array would bypass Proxy traps; immutable methods produce a new array that can be assigned to the reactive state property, triggering the set trap correctly). Array.prototype.with(index, value) returns a copy of the array with the element at the specified index replaced — the immutable equivalent of array[index] = value. For Set: the ES2024 Set methods (Set.prototype.union(), Set.prototype.intersection(), Set.prototype.difference()) were not in ES2023 but are already available in Chrome 122+ and Safari 17+. Change array by copy is the collective name for toReversed, toSorted, toSpliced, and with. Hashbang support (#!/usr/bin/env node as the first line of a JS file) is now part of the spec, formalizing what Node.js already supported. The reactive state management post used Proxy for reactive stores; ES2023 immutable array methods are the natural companion for mutating state in those stores.
Problem: A WordPress admin JavaScript module manages a list of notifications — the code uses Array.reverse() to show the most recent first, but this mutates the shared state array and breaks the Proxy-based reactive store; sort() and splice() similarly mutate the original array, requiring manual [...array] spread copies before every sort and filter operation.
Solution: Replace the mutating array methods with ES2023 immutable equivalents — toReversed(), toSorted(), toSpliced(), and with() — which return new arrays and work correctly with Proxy reactive stores.
// ── ES2023 Array methods for WordPress admin state management ───────────────
// Sample notifications state
let notifications = [
{ id: 1, text: 'Plugin activated', timestamp: 1700000000, read: true },
{ id: 2, text: 'Update available', timestamp: 1700001000, read: false },
{ id: 3, text: 'Backup completed', timestamp: 1700002000, read: false },
];
// ── findLast / findLastIndex ──────────────────────────────────────────────────
// Find the most recent unread notification (last matching from the end)
const lastUnread = notifications.findLast(n => !n.read);
// { id: 3, text: 'Backup completed', ... }
const lastUnreadIndex = notifications.findLastIndex(n => !n.read);
// 2
// ── toReversed — immutable reverse (no mutation) ──────────────────────────────
// Before ES2023:
// const reversed = [...notifications].reverse(); // manual copy needed
// ES2023:
const newestFirst = notifications.toReversed();
// notifications is unchanged; newestFirst is a new array in reverse order
// ── toSorted — immutable sort ─────────────────────────────────────────────────
// Sort by timestamp descending without mutating notifications
const sortedByTime = notifications.toSorted((a, b) => b.timestamp - a.timestamp);
// ── toSpliced — immutable splice ──────────────────────────────────────────────
// Remove 1 item at index 1 without mutating
const withoutSecond = notifications.toSpliced(1, 1);
// [item0, item2] — notifications still has all 3 items
// Insert a new notification at index 0
const newNotification = { id: 4, text: 'Cache cleared', timestamp: Date.now(), read: false };
const withNew = notifications.toSpliced(0, 0, newNotification);
// [newNotification, ...notifications]
// ── with — immutable index replacement ───────────────────────────────────────
// Mark notification at index 1 as read
const afterMarkRead = notifications.with(1, { ...notifications[1], read: true });
// notifications[1] still has read: false; afterMarkRead[1] has read: true
// ── Integration with Proxy reactive store ────────────────────────────────────
// Because these methods return new arrays instead of mutating in place,
// assigning them to a reactive state property correctly triggers the Proxy set trap:
const { state, subscribe } = createStore({ notifications });
subscribe('notifications', (newList) => {
renderNotificationList(newList);
});
// This triggers the Proxy set trap and calls subscribe callbacks:
state.notifications = state.notifications.toSpliced(0, 0, newNotification);
// ── Practical: filter + sort pipeline returning new arrays ────────────────────
function getDisplayNotifications(allNotifications, { showRead = false } = {}) {
return allNotifications
.filter(n => showRead || !n.read) // filter returns new array
.toSorted((a, b) => b.timestamp - a.timestamp); // toSorted returns new array
}
NOTE: If you use wp-scripts (based on webpack/babel) for your WordPress JavaScript build, these ES2023 methods are available without any polyfills when your browserslist targets modern browsers — they are native language methods, not syntax features, so Babel cannot polyfill them via transpilation. If you need to support older browsers (e.g., Safari 15.x, which lacks toSorted), add core-js with useBuiltIns: 'usage' in your Babel config, which will add the polyfill automatically when it detects Array.prototype.toSorted usage. For Node.js tooling scripts (Gulp, custom build scripts), Node.js 20+ supports all ES2023 Array methods natively — no polyfill needed.