JavaScript Merge Two Objects: Three Approaches Quiz
Three seeded ways to merge two plain objects (spread, `Object.assign`, and a manual `for...in` copy), plus two companions on shallow-vs-deep semantics and on which approaches mutate the target.
549 views
17
Implement merge(obj1, obj2) using the spread operator so it returns a new object containing all properties from obj1 and obj2. The original inputs must not be mutated, and obj2 keys should win on collision.
Examples
Example 1:
Input: merge({a: 1, b: 2}, {c: 3, d: 4, e: 5})
Output: { a: 1, b: 2, c: 3, d: 4, e: 5 }
Explanation: spread copies own enumerable keys from each source into a fresh object, in the order they appear.const merge = (obj1, obj2) => {
// use object spread
};
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4, e: 5 };
console.log(merge(obj1, obj2));Implement merge(obj1, obj2) using Object.assign. Demonstrate the difference between Object.assign(obj1, obj2) (mutates obj1) and Object.assign({}, obj1, obj2) (returns a fresh object).
Examples
Example 1:
Input:
const a = {x: 1};
const b = {y: 2};
Object.assign(a, b);
console.log(a);
Output: { x: 1, y: 2 }
Explanation: Object.assign with a non-empty target mutates that target and returns it.Example 2:
Input:
const c = Object.assign({}, {x: 1}, {y: 2});
Output: { x: 1, y: 2 } (and the two source objects remain unchanged)
Explanation: seeding with {} gives a fresh target so the sources are not mutated.// show both Object.assign forms: mutating and non-mutating
const a = { x: 1 };
const b = { y: 2 };
Object.assign(a, b);
console.log(a);
const c = Object.assign({}, { x: 1 }, { y: 2 });
console.log(c);Implement merge(obj1, obj2) manually with a for...in loop. Use Object.prototype.hasOwnProperty to filter out inherited keys, and build a fresh result without mutating the inputs.
Examples
Example 1:
Input: merge({a: 1, b: 2}, {c: 3, d: 4, e: 5})
Output: { a: 1, b: 2, c: 3, d: 4, e: 5 }
Explanation: copy obj1's own keys to a fresh result, then copy obj2's own keys on top so obj2 wins on collision.const merge = (obj1, obj2) => {
// walk each object with for...in, guard with hasOwnProperty
// copy obj1 first, then obj2 so collisions resolve to obj2's value
};
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4, e: 5 };
console.log(merge(obj1, obj2));Predict the output of merging two objects whose values are themselves objects. Why does a shallow merge leave both sources sharing the same nested reference?
Examples
Example 1:
Input:
const a = { nested: { x: 1 } };
const b = { extra: true };
const merged = { ...a, ...b };
merged.nested.x = 99;
console.log(a.nested.x);
Output: 99
Explanation: spread copies only top-level keys; merged.nested and a.nested point to the same object, so mutating one is visible through the other.const a = { nested: { x: 1 } };
const b = { extra: true };
const merged = { ...a, ...b };
merged.nested.x = 99;
console.log(a.nested.x);Rank merge implementations by mutation safety: which forms leave both inputs untouched, and which forms mutate one of them by default?
Examples
Example 1:
Input: classifications for spread, Object.assign(target, source), Object.assign({}, ...), and the for...in copy
Output:
immutable: { ...obj1, ...obj2 }; Object.assign({}, obj1, obj2); for...in copy into a fresh {}
mutating: Object.assign(obj1, obj2) (writes into obj1)
Explanation: only Object.assign with a real target as the first argument mutates by default; every other form starts from a fresh container.// classify each merge form as immutable or mutating