JS Object Management
In this page:
Merging Objects with Object.assign()
Object.assign(target, source1, source2, ...) copies every enumerable own property from each source object into the target object, in order -- properties from later sources overwrite same-named ones from earlier sources, and the modified target is both mutated and returned.
Note: Pass an empty object literal ({}) as the target when you want a new merged object without mutating any of the originals: Object.assign({}, obj1, obj2).
Warning: Object.assign(obj1, obj2) mutates obj1 directly, which can be surprising if you expected it to leave both original objects untouched.
Example: Merging Objects with Object.assign()
const defaults = { theme: "light" };
const overrides = { theme: "dark" };
const merged = Object.assign({}, defaults, overrides);
console.log(merged);
Merging Objects with Spread Syntax
The spread operator inside an object literal, {...obj1, ...obj2}, achieves the same merging behavior as Object.assign() with more concise, readable syntax -- and always creates a brand-new object, never mutating any of the source objects.
Note: Prefer spread syntax over Object.assign() for merging in new code, since it reads more clearly and never risks accidentally mutating an existing object.
Warning: Like Object.assign(), spread-based merging only copies properties one level deep -- nested objects remain shared references, not independent copies.
Example: Merging Objects with Spread Syntax
const defaults = { theme: "light" };
const overrides = { theme: "dark" };
const merged = { ...defaults, ...overrides };
console.log(merged);
The Shallow Copy Limitation
Both Object.assign() and spread syntax perform a shallow copy -- top-level properties are genuinely copied, but if a property's value is itself an object or array, only the reference to that nested structure is copied, meaning the original and the copy still share and can mutate the same nested data.
Note: When a deep, fully independent copy is genuinely needed (nested objects included), use structuredClone() (built into modern browsers) rather than Object.assign() or spread.
Warning: Modifying a nested object through the "copy" can unexpectedly also change the original, since the shallow copy only duplicated the outer object, not the nested one inside it.
Example: The Shallow Copy Limitation
const original = { info: { city: "Delhi" } };
const copy = { ...original };
copy.info.city = "Mumbai";
console.log(original.info.city); // "Mumbai" - nested object shared
Building an Object from Entries with Object.fromEntries()
Object.fromEntries(arrayOfPairs) is the reverse operation of Object.entries() -- it takes an array of [key, value] pairs and builds a plain object from them, useful after transforming data with array methods (like filter or map) and wanting the result back as an object.
Note: Combine Object.entries(), array methods, and Object.fromEntries() as a common pattern: convert an object to pairs, transform the pairs with array methods, then convert back to an object.
Warning: Object.fromEntries() expects genuinely two-item [key, value] pairs -- passing malformed pairs (missing a value, for instance) produces properties set to undefined rather than an error.
Example: Building an Object from Entries with Object.fromEntries()
const pairs = [["a", 1], ["b", 2]];
console.log(Object.fromEntries(pairs));
Checking Property Existence and Removing Properties
in and hasOwnProperty() both check whether a property exists on an object, and delete removes a property from an object entirely -- three complementary tools for managing an object's shape beyond just reading and setting values.
Note: Prefer obj.hasOwnProperty(key) over the in operator when you specifically want to exclude inherited properties from the check.
Warning: delete removes a property but does not affect other references to the same object elsewhere in your code -- all of them will see the property gone, since there is still only one underlying object.
Example: Checking Property Existence and Removing Properties
const user = { name: "Sam" };
console.log("name" in user);
console.log(user.hasOwnProperty("name"));
delete user.name;
console.log(user);
- Assuming Object.assign() or spread syntax performs a deep copy -- both only copy properties one level deep, so a nested object or array is still shared by reference between the original and the copy.
- Forgetting that later arguments to Object.assign() (or later spread values) overwrite earlier ones when property names collide, and getting the intended merge priority backward.
- Using Object.assign(target, source) and forgetting that it mutates the target object directly -- passing an empty object literal as the first argument avoids accidentally mutating an existing object.
- Object.assign(target, ...sources) copies properties from one or more source objects into a target object, and returns that target.
- The spread operator ({...obj1, ...obj2}) offers similar merging behavior with more concise syntax.
- Both Object.assign() and spread perform a shallow copy -- nested objects/arrays remain shared by reference, not duplicated.
Object.assign() and object spread syntax are both supported in every modern browser (spread syntax for objects specifically since ES2018).
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: