Modern syntax
Destructuring, spread and rest, chaining, nullish, and modules in short.
Modern syntax removes ceremony: names for the pieces, safe deep access,
sane defaults. Interviewers ask this to check you write current JavaScript —
and know which sugar hides real behavior (shared references, silent
undefined).
Real-life situation
A settings screen merges saved preferences over defaults, reads an
optional support email, and totals a variable list of fees. Spread merges
one level, ?. short-circuits the missing contact, ?? keeps a real zero
page number, and rest gathers the fees — four features, zero helper
functions.
Visual
Try it
function renderCard(user) {
const { name, email, role } = user;
const label = role ?? "member";
return name + " <" + email + "> (" + label + ")";
}
const ada = { name: "Ada", email: "ada@example.com" };
console.log(renderCard(ada));
const base = { theme: "dark", page: 1 };
const next = { ...base, page: 2 };
console.log(next.page);
console.log(base.page);
const order = { id: 7 };
console.log(order.customer?.email ?? "no email");
const order2 = { id: 8, customer: { email: "a@b.co" } };
console.log(order2.customer?.email ?? "no email");
function total(...nums) {
return nums.reduce(function (s, n) {
return s + n;
}, 0);
}
console.log(total(1, 2, 3));Expected output
Ada <ada@example.com> (member) 2 1 no email a@b.co 6
Try giving ada a role: "" and watch ?? keep it while || would not.
Then nest one more level in base and share it on purpose.
ES modules versus CommonJS, in short
ES modules use static import/export that bundlers analyze and
tree-shake; one file, one scope, always strict. CommonJS uses runtime
require/module.exports — flexible but opaque. Browsers speak ESM; Node
reads both and picks by extension and package.json type.
import { total } from "./cart.js";Missing link — guess first, then reveal.
const order = {};
console.log(order.customer?.email ?? "missing");Interview questions
What does destructuring buy you?basic
Names for the pieces, at the use site: const { name, price } = item instead of three item. prefixes, with renaming ({ name: label }) and defaults ({ qty = 1 }) built in. It shines in function parameters — render({ title, items }) documents the expected shape — and in swapping values without a temp. Over-destructure (five levels deep) and readability reverses, so stop at one or two levels.
Interviewers also ask
- How do you rename while destructuring?
What is the difference between spread and rest?basic
Same ... spelling, opposite jobs, told apart by position. Spread EXPANDS: [...old, item] pouring values out. Rest GATHERS: function sum(...nums) collecting leftovers in. Spread copies one level (nested objects stay shared); rest always builds a true array. Say "expand versus gather" and the follow-ups get easy.
Interviewers also ask
- Is a rest parameter a real array?
When do you use template literals beyond simple strings?basic
Any time a string has moving parts: readable interpolation (Hi ${name}, ${count} items), multi-line messages without \n juggling, and tagged templates for escaping (SQL builders, CSS-in-JS). The interview trap is nesting backticks or forgetting ${} around expressions — both read fine at a glance and fail at runtime, so slow down on template lines.
Interviewers also ask
- How do you nest a template inside one?
What problem does optional chaining solve?basic
Deep access without the pyramid of guards: order?.customer?.email short-circuits to undefined at the first missing link instead of throwing. It also works for calls (user.save?.()) and brackets (cache?.[key]). The catch: it hides WHICH link was missing, so for required data prefer explicit checks that fail loudly over silent undefined spreading downstream.
Interviewers also ask
- What does it hide that explicit checks show?
What is the difference between ES modules and CommonJS?intermediate
ES modules use static import/export the bundler can analyze (tree shaking, circular-import warnings); one file, one scope, always strict. CommonJS uses runtime require/module.exports — flexible and dynamic, but opaque to static analysis. Browsers and modern tooling speak ESM; Node supports both, resolving .mjs versus .cjs (and package.json type) when they collide.
Interviewers also ask
- Can you require an ES module from CommonJS?
How do default and named exports differ, and which should you use?intermediate
Named exports (export function total) can be many per file, keep their names (refactors and autocomplete survive), and tree-shake cleanly — prefer them. Default exports (export default) allow one per file with any local name at import, which reads nicely but hides renames and complicates re-exports. Mixed style across a codebase is the real smell; pick named and stay consistent.
Interviewers also ask
- Why do barrel files slow down large apps?
What is the spread-based update pattern for nested state?basic
Copy every level on the path to the change: setUser({ ...user, address: { ...user.address, city } }). Each spread preserves the siblings at its level while replacing the edited branch — the core immutable-update move in UI code. It gets noisy past two levels, which is exactly when interviewers expect you to mention a helper library or structuredClone instead of a third nested spread.
Interviewers also ask
- When does this pattern stop scaling?
Key takeaways
- Destructure for names, spread to expand, rest to gather.
?.short-circuits missing links;??defaults only nullish values.- ESM is static and shakable; CommonJS is dynamic and opaque.
References
Last verified: 2026-10-12.
Runner helpers
sleep(ms)waits;fakeFetch(url)returns deterministic sample data. Console code runs in a worker with a 5-second limit.