Use an array when order matters, an object for a record with named fields, a Map for key/value lookup, and a Set for unique values. Choosing a collection is about its behavior, not about finding the shortest syntax. Arrays and objects are mutable; copying the binding does not copy the value it refers to.
Transform without surprising the caller
const sessions = [
{ topic: "JavaScript", minutes: 25 },
{ topic: "TypeScript", minutes: 15 },
{ topic: "JavaScript", minutes: 35 },
];
const longTopics = sessions.filter(s => s.minutes >= 25).map(s => s.topic);
const unique = [...new Set(longTopics)];
const totals = new Map();
for (const session of sessions) {
totals.set(session.topic, (totals.get(session.topic) ?? 0) + session.minutes);
}
const sorted = [...sessions].sort((a, b) => a.minutes - b.minutes);
const updated = sessions.map((session, index) =>
index === 0 ? { ...session, minutes: 30 } : session
);
console.log(unique.join(", "));
console.log(totals.get("JavaScript"));
console.log(sorted[0].minutes, sessions[0].minutes, updated[0].minutes);
Expect JavaScript, 60, and 15 25 30. filter selects records, map creates transformed values, and the loop builds a lookup table. An empty input should produce an empty result rather than crashing. If using reduce, provide a suitable initial accumulator so that empty arrays have defined behavior.
sort changes its array. Copying before sorting protects the outer array, but both arrays still refer to the same session objects. Object spread is also a shallow copy: nested objects remain shared. The update above creates a new record only for the changed session. Use immutable updates where callers depend on previous state, but do not assume copying makes all nested data immutable.
Identity, iteration and serialization
Two separate objects with identical fields are not strictly equal. A Set containing two separate object values retains both; it does not deduplicate by their titles. For deduplication by a field, explicitly choose a key and decide which record wins. A Map also compares object keys by identity. Arrays, Maps and Sets can be visited with for...of; array forEach does not wait for an async callback, so do not use it to sequence asynchronous work.
Destructuring extracts fields or positions, and a default only applies to undefined. Optional chaining safely stops at a nullish base; it does not validate arbitrary data or make calling a non-function safe. Use find when one match is needed and handle its undefined result.
JSON is a data format, not a general snapshot of a JavaScript program. JSON round-tripping loses undefined object fields and does not preserve Maps, Sets, functions or Date instances as those types. Cycles fail serialization. For a network boundary, define a small JSON-compatible shape and validate it after parsing. Use a known timezone when presenting dates; parsing an arbitrary locale-formatted date is not a portable storage format. Regular expressions help with bounded text matching, but complex patterns are not a substitute for domain validation.
Exercise: deduplicate sessions by topic while keeping the longest session for each topic. Return new records sorted alphabetically without modifying the input.
Solution guidance: accumulate into a Map keyed by topic, compare durations explicitly, then spread its values into an array. Copy selected records if consumers must not share mutable objects. Test ties, empty input and two records that have the same title but different identities.
References: Indexed collections, objects.
Previous: Functions, Scope and Closures. Next: this, Prototypes and Classes.

