JavaScript: Array and Object Advanced Methods
Master map, filter, reduce, method chaining, Object utilities, and every copying strategy from shallow to deep.
map(): Transform Every Element
map() creates a new array by running a callback on every element. The original array is never mutated.
map()
Use map() whenever you need a new array of the same length with each element transformed.
- Always returns a new array of the same length as the input
- The callback receives
(element, index, array) - Common patterns: extract a field, format values, convert types
- Chain with
filter()to transform only matching items
map() Patterns
Extract fields, add computed properties, or convert values, always a new array.
Press Run to execute the code and see output here.
filter(): Keep Matching Elements
filter() creates a new array containing only the elements for which the callback returns a truthy value.
filter()
Use filter() to narrow down a dataset, the result may be shorter than the input.
- Returns a new array with 0 to n elements never mutates the original
- The callback receives
(element, index, array)and must return truthy/falsy - Chain with
map()to filter then transform - Use
Booleanas the callback to remove all falsy values:.filter(Boolean)
filter() Patterns
Keep only elements that satisfy a condition, chain with map() for transform-after-filter.
Press Run to execute the code and see output here.
reduce(): Accumulate to a Single Value
reduce() iterates over an array and accumulates a result, the most powerful and flexible array method.
reduce(callback, initialValue)
reduce() can produce any output type: a number, string, object, or array.
- Callback receives
(accumulator, currentValue, index, array) - Always provide an initial value as the second argument to avoid bugs on empty arrays
- Can replace any combination of map + filter when performance is critical
- Common uses: sum, groupBy, counting, flattening, building objects from arrays
reduce() Patterns
Sum totals or group data into objects, the accumulator can be any shape.
Press Run to execute the code and see output here.
Method Chaining
Because array methods return new arrays, you can chain them directly without intermediate variables. The result of one method becomes the input of the next.
Method Chaining
Chains read as a pipeline, each step passes its result to the next without storing it in a variable.
- Read left-to-right as a data pipeline: source → filter → map → reduce
- Each chained method receives the output of the previous one
- Break long chains onto multiple lines for readability
- Profile before optimising, a single
reduce()can replace a filter + map chain if performance matters
Method Chaining Pipeline
Chain filter, map, and reduce into a readable data pipeline.
Press Run to execute the code and see output here.
Object.keys(), Object.values(), Object.entries()
These three static methods convert an object's structure into arrays, making it easy to iterate, filter, or transform object data using array methods.
Object to Array Conversions
Converting objects to arrays unlocks the full power of map, filter, and reduce on object data.
Object.keys(obj): array of own enumerable property namesObject.values(obj): array of own enumerable property valuesObject.entries(obj): array of[key, value]pairs- All three only return own enumerable properties, inherited ones are excluded
Object.keys / values / entries
Convert object data into arrays to use filter, map, and reduce on it.
Press Run to execute the code and see output here.
Object.fromEntries()
Object.fromEntries() is the inverse of Object.entries(), it converts an array of [key, value] pairs back into an object.
Object.fromEntries()
Combine with Object.entries() and map() to transform object properties cleanly.
- Accepts any iterable of
[key, value]pairs, including a Map - Perfect for transforming object values: entries → map → fromEntries
- Replaces the verbose
Object.keys().reduce()pattern - Also converts a Map directly to a plain object
Object.fromEntries()
Transform object values or filter keys by round-tripping through entries.
Press Run to execute the code and see output here.
Object.getOwnPropertyNames()
Unlike Object.keys(),Object.getOwnPropertyNames() returns all own property names including non-enumerable ones.
Object.getOwnPropertyNames()
Use when you need to inspect hidden or non-enumerable properties that Object.keys() skips.
- Returns all own property names: enumerable AND non-enumerable
- Does NOT include Symbol-keyed properties (use
Object.getOwnPropertySymbols()for those) - Useful for inspecting class instances, methods defined on prototypes are not included
- Non-enumerable properties are created with
Object.defineProperty()
Object.getOwnPropertyNames()
Reveals non-enumerable properties that Object.keys() hides.
Press Run to execute the code and see output here.
Object.defineProperty()
Object.defineProperty() adds or modifies a property with fine-grained control over its behaviour whether it can be written, enumerated, or deleted.
Object.defineProperty()
Use defineProperty when you need to lock down properties or add computed getters to an object.
writable: false: value cannot be changed (throws in strict mode)enumerable: false: hidden fromfor...inandObject.keys()configurable: false: property cannot be deleted or redefined- Use
get/setdescriptor keys to define a getter/setter property
Object.defineProperty()
Create read-only constants or computed getter properties with full descriptor control.
Press Run to execute the code and see output here.
Shallow vs Deep Copying
A shallow copy duplicates the top-level properties but nested objects are still shared references. A deep copy produces a completely independent clone with no shared references at any depth.
Shallow Copy
Object.assign() and spread both create shallow copies modifying nested objects still affects the original.
Object.assign({}, source): copies own enumerable properties one level deep{ ...source }: same as Object.assign, spread is shallow- Safe for flat objects with only primitive values
- Unsafe if the object contains nested objects, arrays, or Dates
Shallow Copy Limitation
Spread copies the top level only, nested objects are still the same reference.
Press Run to execute the code and see output here.
Deep Copying Strategies
For nested objects you need a deep copy. Three approaches exist, each with trade-offs.
Deep Copy Options
Use structuredClone() in modern environments, it handles dates, sets, maps, and circular references.
JSON.parse(JSON.stringify(obj)): simple but loses Dates, functions, undefined, SymbolsstructuredClone(obj): modern, built-in, handles Date, Map, Set, ArrayBuffer, circular refs- Third-party libraries (Lodash
_.cloneDeep): handles edge cases, works in older environments - For plain data objects with no special types, the JSON trick is still common and fine
Deep Copy Strategies
structuredClone() is the modern choice, JSON trick works for plain serialisable data.
Press Run to execute the code and see output here.
| Method | Depth | Handles Date / Map / Set | Circular refs |
|---|---|---|---|
{ ...obj } / Object.assign() | Shallow | No | No |
JSON.parse(JSON.stringify()) | Deep | No, Dates become strings | No, throws |
structuredClone() | Deep | Yes | Yes |
_.cloneDeep() (Lodash) | Deep | Yes | Yes |
Knowledge Check
1. What does map() return?
2. What does reduce() use as its starting accumulator when no initial value is provided?
3. What does Object.entries() return?
4. What does Object.fromEntries() do?
5. What is the limitation of the spread operator when copying objects?
6. Which method creates a true deep clone of an object including nested structures in modern JS?
7. What is method chaining with array methods?