Free JavaScript reference · Python timeline
JavaScript ES2018: Object copies and asynchronous cleanup
Object rest/spread collects or copies properties, promise finally handles cleanup, and asynchronous iteration becomes language syntax.
Edition 9 · Published · Editorial review October 26, 2026
Standardized in ES2018 · Syntax
Object rest and spread
Object spread copies own enumerable properties into a new object. Later properties overwrite earlier ones, which is useful for defaults and overrides. Object rest collects the properties not already selected by a destructuring pattern.
These operations are shallow. Nested objects remain shared, so changing a nested field through the copy can affect the original. They do not preserve a class instance's prototype or every property descriptor.
The example extracts a title and keeps the remaining options, then overrides one of them in a new object. Choose cloning behavior deliberately rather than treating spread as a universal copy function.
Worked example
Uses ES2018 features · Script
const options = {title: "Report", size: 12, theme: "light"}; const {title, ...rest} = options; const larger = {...rest, size: 16}; console.log(title, larger.size, options.size);
Expected output
Report 16 12
Example checked with Chromium 151.0.7922.34, Node.js 24.19.0.
Common mistake
Reversing the property order changes which value wins. Copying the outer object does not isolate nested mutable values.
Try it yourself
Add a nested settings object and mutate it through a spread copy. Explain which reference is shared.
Read more: ES2018 specification · MDN explanation and compatibility
Standardized in ES2018 · Built-in async API
Promise.finally() preserves settlement
A finally callback runs when a promise settles, making it useful for cleanup that belongs to both success and failure. If the callback completes normally, the next promise keeps the original fulfilled value or rejection reason.
The callback receives no result argument. Returning an ordinary value from it does not replace the successful result. Throwing or returning a rejected promise can, however, make cleanup failure become the resulting rejection.
The example shows cleanup happening before a later success handler, while the value remains six. Use then or catch when the goal is transforming the result.
Worked example
Uses ES2018 features · Script
const finished = Promise.resolve(6) .finally(() => { console.log("cleanup"); return 99; }) .then(value => console.log(value));
Expected output
cleanup
6
Example checked with Chromium 151.0.7922.34, Node.js 24.19.0.
Common mistake
A finally callback can itself fail. Do not assume cleanup is harmless or that its return value replaces the original success value.
Try it yourself
Change the callback to throw an Error, then add a catch. Which result reaches the final observer?
Read more: ES2018 specification · MDN explanation and compatibility
Standardized in ES2018 · Syntax
Async generators and for await...of
An async generator can yield a sequence of eventual values. for await...of consumes an asynchronous iterable one step at a time, awaiting each result before entering the body.
This is useful for streams of records or paged data, though the syntax does not itself fetch anything. The example uses a tiny local generator so its behavior does not depend on a service or file.
The loop belongs inside an async function in this script. Breaking from the loop can trigger generator cleanup; resource-owning generators should arrange their cleanup carefully.
Worked example
Uses ES2018 features · Script
async function* numbers() { yield 2; yield Promise.resolve(3); } async function report() { let total = 0; for await (const value of numbers()) total += value; console.log(total); } const finished = report();
Expected output
5
Example checked with Chromium 151.0.7922.34, Node.js 24.19.0.
Common mistake
for await is not the same as starting all operations concurrently. Sequential consumption may be exactly what is needed for a stream.
Try it yourself
Add a third yielded value and predict the total. Then consider where cleanup belongs if a consumer stops early.
Read more: ES2018 specification · MDN explanation and compatibility
Recap
Object rest/spread collects or copies properties, promise finally handles cleanup, and asynchronous iteration becomes language syntax. Check the engines your project supports before adopting new syntax or built-ins.
Read the ES2018 specification →