All jobs / Frontend / web developer
JavaScript interview questions
JavaScript questions a Frontend / web developer can be asked, from first job to senior. Open one to see the strongest answer and why it works.
They ask why 0 == '' is true and why you would not write that check. Strongest explanation?
The strongest answer: Say == coerces types; use === (or Object.is) and treat empty string and zero as separate cases
Why it works: Naming coercion and choosing === is the junior bar; then handle 0 and '' explicitly if both are valid.
- Explain coercion, then refuse it in app code.
- == turns values into a common type first.
- === compares type and value.
- If 0 and '' are both legal, check them by name.
typeof null is 'object'. How do you safely check for a real object versus null?
The strongest answer: Check value !== null && typeof value === 'object', and use Array.isArray when arrays must be excluded
Why it works: The historic typeof bug is the prompt; the fix is an explicit null check (and array if it matters).
- Don't trust typeof alone for objects.
- Reject null explicitly.
- Decide whether arrays count as objects.
- Prefer a schema/guard once the shape matters.
An API sometimes returns an empty body. How do you parse it safely?
The strongest answer: Check status and whether a body exists (content-type / length); only json() when there is JSON; handle parse errors
Why it works: Empty 204s and HTML error pages are why you look before you parse.
- Parse only what is JSON.
- Read status and content-type first.
- Skip json() on empty bodies.
- Catch parse errors; never eval.
A form reloads the page when you click Save, and you wanted to POST with fetch. What did you miss?
The strongest answer: Handle submit on the form, call preventDefault, then fetch — do not rely only on the button click
Why it works: Enter in a field fires submit, not your button handler. preventDefault on submit, then fetch.
- Own the submit event.
- Listen on the form, not only the button.
- preventDefault, then fetch and handle status.
- Never put secrets on the query string.
A list will grow to hundreds of rows, each with a Delete control. How do you attach clicks?
The strongest answer: Listen on the list parent and read the row id from the event target so new rows work without rebinding
Why it works: Delegation is the vanilla answer: one listener, stable as the list grows. In React, one handler on the parent is the same idea.
- One listener, many rows.
- Attach at the list, not each button.
- Identify the row from the target or a data attribute.
- In React, the same rule: a parent handler plus a stable id.
fetch('/api/items') resolves but the UI is useless on a 500. What do you check?
The strongest answer: Say fetch only rejects on network failure — check response.ok or status, then parse the body, then show a real error
Why it works: This is the classic fetch pitfall: HTTP errors are successful promises. Branch on status first.
- Treat HTTP status as part of the contract.
- fetch rejects on network, not on 404/500.
- Branch on ok/status before parsing.
- Show a human error; back off if you retry.
Typeahead fires a request per keystroke. How do you fix it without dropping the last query?
The strongest answer: Debounce the request, cancel in-flight work with AbortController, and send the latest term
Why it works: Debounce reduces traffic; abort keeps the last term winning.
- Latest query wins.
- Debounce the call.
- Abort the previous request.
- Apply only the response that matches the current term.
'1 files' and Hebrew plural forms are wrong. What does the i18n layer need?
The strongest answer: ICU/CLDR plural categories per locale — not an English-only count === 1 check
Why it works: Pluralization is a locale table, not a boolean. Hebrew, Russian, and Arabic are the usual interview examples.
- Use real plural rules.
- ICU messages, not if (count === 1).
- Translators fill each category.
- Don't hide the number.