JS

Modern Features

JavaScript · 10 entries

structuredClone()

syntax
const clone = structuredClone(value);
example
const original = {
  name: "Ava",
  scores: [95, 88, 72],
  metadata: { joined: new Date("2024-01-15") },
};
const clone = structuredClone(original);
clone.scores.push(100);
clone.metadata.joined.setFullYear(2025);

console.log(original.scores);          // [95, 88, 72]
console.log(original.metadata.joined); // 2024-01-15 (unchanged)

Note Built-in deep clone that handles Dates, Maps, Sets, RegExps, ArrayBuffers, circular references. Cannot clone functions, DOM nodes, or Error objects.

Array/String .at() Method

syntax
arr.at(index)
str.at(index)
example
const stack = ["first", "second", "third", "last"];
console.log(stack.at(0));   // "first"
console.log(stack.at(-1));  // "last"
console.log(stack.at(-2));  // "third"

console.log("hello".at(-1)); // "o"

Note Works on Arrays, Strings, and TypedArrays. The main advantage over bracket notation is support for negative indices.

findLast() and findLastIndex()

syntax
arr.findLast(callback)
arr.findLastIndex(callback)
example
const transactions = [
  { type: "credit", amount: 500 },
  { type: "debit", amount: 200 },
  { type: "credit", amount: 300 },
  { type: "debit", amount: 150 },
];

const lastCredit = transactions.findLast(t => t.type === "credit");
console.log(lastCredit); // { type: "credit", amount: 300 }

const lastCreditIdx = transactions.findLastIndex(t => t.type === "credit");
console.log(lastCreditIdx); // 2

Note ES2023. Searches from the end of the array. More readable and efficient than reversing first or using a manual reverse loop.

Object.groupBy()

syntax
Object.groupBy(iterable, keyFn)
example
const people = [
  { name: "Ava", department: "Engineering" },
  { name: "Bo", department: "Design" },
  { name: "Cara", department: "Engineering" },
  { name: "Dan", department: "Design" },
  { name: "Eve", department: "Marketing" },
];

const byDept = Object.groupBy(people, p => p.department);
console.log(byDept.Engineering);
// [{ name: "Ava", ... }, { name: "Cara", ... }]
console.log(Object.keys(byDept));
// ["Engineering", "Design", "Marketing"]

Note ES2024. Returns a null-prototype object. For Map output, use Map.groupBy() instead. Replaces the common reduce-based grouping pattern.

Map.groupBy()

syntax
Map.groupBy(iterable, keyFn)
example
const items = [
  { name: "Apple", price: 1.2 },
  { name: "Steak", price: 15 },
  { name: "Bread", price: 2.5 },
  { name: "Salmon", price: 12 },
];

const byRange = Map.groupBy(items, item =>
  item.price > 10 ? "expensive" : "affordable"
);
console.log(byRange.get("expensive"));
// [{ name: "Steak"... }, { name: "Salmon"... }]

Note ES2024. Similar to Object.groupBy but returns a Map, which supports any key type (objects, symbols, etc.).

Set Methods (ES2025)

syntax
setA.union(setB)
setA.intersection(setB)
setA.difference(setB)
setA.symmetricDifference(setB)
setA.isSubsetOf(setB)
setA.isSupersetOf(setB)
setA.isDisjointFrom(setB)
example
const frontend = new Set(["js", "css", "html", "ts"]);
const backend = new Set(["js", "python", "go", "ts"]);

console.log(frontend.union(backend));
// Set {"js", "css", "html", "ts", "python", "go"}

console.log(frontend.intersection(backend));
// Set {"js", "ts"}

console.log(frontend.difference(backend));
// Set {"css", "html"}

console.log(frontend.isSubsetOf(backend)); // false

Note ES2025. All methods return new Sets (non-mutating). Works with any iterable argument, not just Sets. Replaces manual loop-based set operations.

Promise.withResolvers()

syntax
const { promise, resolve, reject } = Promise.withResolvers();
example
function createDeferred() {
  const { promise, resolve, reject } = Promise.withResolvers();
  return { promise, resolve, reject };
}

const deferred = createDeferred();

// Resolve from elsewhere
setTimeout(() => deferred.resolve("Done!"), 1000);

const result = await deferred.promise;
console.log(result); // "Done!"

Note ES2024. Eliminates the common pattern of extracting resolve/reject from the Promise constructor. Useful for event-based resolution and deferred patterns.

Iterator Helpers (ES2025)

syntax
iterator.map(fn)
iterator.filter(fn)
iterator.take(n)
iterator.drop(n)
iterator.flatMap(fn)
iterator.toArray()
example
function* naturals() {
  let n = 1;
  while (true) yield n++;
}

// Get first 5 even squares
const result = naturals()
  .map(n => n ** 2)
  .filter(n => n % 2 === 0)
  .take(5)
  .toArray();

console.log(result); // [4, 16, 36, 64, 100]

Note ES2025. Chainable lazy operations on any iterator. Unlike array methods, these process elements one at a time, making them memory-efficient for large or infinite sequences.

Explicit Resource Management (using)

syntax
using resource = acquireResource();
await using resource = acquireAsyncResource();
example
class TempFile {
  constructor(path) {
    this.path = path;
    console.log(`Created: ${path}`);
  }

  [Symbol.dispose]() {
    console.log(`Cleaned up: ${this.path}`);
  }
}

{
  using file = new TempFile("/tmp/data.txt");
  // Use file here...
} // Automatically calls file[Symbol.dispose]() when block exits
output
"Created: /tmp/data.txt"
"Cleaned up: /tmp/data.txt"

Note TC39 Stage 3 (expected in ES2025/2026). Similar to Python's 'with' or C#'s 'using'. Guarantees cleanup even if an error is thrown. Use Symbol.asyncDispose for async cleanup.

RegExp v Flag (Unicode Sets)

syntax
/pattern/v
example
// Match any emoji using Unicode property
const emojiPattern = /\p{Emoji_Presentation}/v;
console.log(emojiPattern.test("hello")); // false
console.log(emojiPattern.test("hi [U+D83D][U+DC4B]")); // true

// Set operations in character classes
const greekLetters = /[\p{Script=Greek}&&\p{Letter}]/v;
console.log(greekLetters.test("α")); // true

Note ES2024. The v flag replaces the u flag with enhanced Unicode support and set operations (&&, --) inside character classes.