You may understand const name = student.name and still pause when the same job appears as const { name } = student. The confusion grows because ... can collect or expand values. A single source value can be transformed through array and object patterns, defaults, renaming, rest, spread, and shallow-copy traps.
Destructuring means matching a pattern to a value
Destructuring binds array elements or object properties to variables. Direct access and a pattern can match:
const scores = [78, 84, 91];
const first = scores[0];
const [firstAgain] = scores;
console.log(first, firstAgain); // 78 78Pattern shape controls the lookup. Square brackets follow positions, while curly braces use object keys.
const student = { id: 42, name: "Asha", city: "Pune" };
const name = student.name;
const { name: sameName } = student;
const [, secondScore] = scores;
const { city } = student;
console.log(name, sameName); // "Asha" "Asha"
console.log(secondScore, city); // 84 "Pune"An empty slot skips position 0. The shorthand { city } uses the same property and variable name. This foundation helps you build practical web-development skills.
Object destructuring: rename, default, and go nested
Keep this object unchanged for the main extraction:
const student = {
id: 42,
name: "Asha",
city: "Pune",
scores: [78, 84, 91],
contact: { email: "asha@example.com" }
};Rename one property and provide a default:
const { name, city: hometown, rank = 1 } = student;The result is name === "Asha", hometown === "Pune", and rank === 1. In city: hometown, city is the source key and hometown is the variable. The default applies because the missing rank is undefined.
Nested patterns can reach deeper:
const { contact: { email } } = student;
console.log(email); // "asha@example.com"This creates email, not a separate contact variable. A default replaces only undefined, not null:
const { points = 0 } = { points: null };
console.log(points); // nullIt also works in a parameter:
const describe = ({ name, city = "Unknown" }) => `${name} from ${city}`;
console.log(describe(student)); // "Asha from Pune"Array destructuring and rest complete the extraction
Patterns can cross objects and arrays:
const { scores: [first, second, ...remaining] } = student;Here, first is 78, second is 84, and remaining is the new array [91]. One statement handles everything:
const {
id,
name,
city: hometown,
scores: [first, second, ...remaining],
contact: { email },
rank = 1
} = student;
console.log(id, name, hometown, first, second, remaining, email, rank);
// 42 "Asha" "Pune" 78 84 [91] "asha@example.com" 1Inside a binding pattern, rest means "collect what is left". Object rest follows the same rule:
const { id: studentId, contact, ...summary } = student;Now studentId === 42, contact.email === "asha@example.com", and summary exactly equals { name: "Asha", city: "Pune", scores: [78, 84, 91] }. Excluded keys do not appear.

Spread expands values into a new container or argument list
Context decides what ... means. Rest collects in a binding pattern. Spread expands in a literal or function call.
const extendedScores = [...student.scores, 96];
const highest = Math.max(...student.scores);
console.log(extendedScores); // [78, 84, 91, 96]
console.log(highest); // 91With object spread, later properties win:
const updatedStudent = { ...student, city: "Delhi" };
const restoredStudent = { city: "Delhi", ...student };updatedStudent.city is "Delhi", but student.city stays "Pune". In reverse order, the later spread restores the original city, so restoredStudent.city is "Pune".
For an immutable array update, copy both changed containers:
const revisedStudent = {
...student,
scores: [...student.scores, 96]
};revisedStudent.scores is [78, 84, 91, 96], while student.scores remains [78, 84, 91]. You can apply this in a full-stack project when updating state without changing its source.
The shallow-copy trap and four failures to recognise
Spread creates a new outer object, not recursive nested copies:
const clone = { ...student };
clone.contact.email = "asha.new@example.com";
console.log(student.contact.email);
// "asha.new@example.com"Both outer objects initially point to the same contact. Copy that level when it must change independently:
const safeClone = {
...student,
contact: { ...student.contact, email: "safe@example.com" }
};Now safeClone.contact.email is "safe@example.com" without another change to student.contact.email.

Failure or trap | What happens | Fix or rule |
|---|---|---|
| It throws a | Use |
| The pattern is invalid. | Rest must be the last element. |
| A bare block is parsed incorrectly for this assignment. | Wrap it: |
|
| Defaults replace |
How coding tests and interviews use this syntax
Common tasks ask you to predict output, repair a pattern, or transform data without mutation. A broader Coding Round Strategy for Placements helps you explain the reason, not just the output.
Consider overwrite order:
const base = { theme: "light", fontSize: 14 };
const choice = { fontSize: 16, compact: true };
const settings = { ...base, ...choice };The result is { theme: "light", fontSize: 16, compact: true }. choice is spread later, so its fontSize value wins.
Predict the output for each expression and identify whether each use of ... is rest or spread:
What do
headandtailcontain inconst [head, ...tail] = [10, 20, 30, 40]? Is...rest or spread?What does
const sum = (a, b, c) => a + b + c; sum(...[4, 7, 9])return? Is...rest or spread?
For the first, head === 10 and tail is [20, 30, 40]. The pattern collects remaining elements, so ...tail is rest. For the second, 4 + 7 + 9 = 20. The call expands the array into three arguments, so ... is spread.
As a cross-language follow-up, Java String Handling: String Pool and Immutability shows how simple-looking syntax can also hide important value and reference behaviour.
The short version and next step
Use object destructuring when names matter and array destructuring when positions matter. Use rest to collect the remainder, and spread to expand values into a new literal or argument list. Remember the two traps: defaults cover undefined, and spread makes only a shallow copy.
Spend 15 minutes on this exact sequence:
Rewrite three direct property reads from
studentas one object pattern.Extract
78,84, and[91]in one nested pattern.Append
96without changing the original scores array.Make an independent update to the nested
contactobject.
Run every snippet and inspect both the new value and the original. Continue the language sequence with the Complete JavaScript course. Then add a second nested field such as contact.phone = "9876543210", predict exactly which references must be copied, and only then run the code.




