JavaScript Coding Interview Questions With Solutions

The JavaScript questions that interviewers ask most often test the language itself, not algorithms: hoisting, this binding, the event loop, closures, and a few array utilities written by hand. The twelve questions below cover that set, grouped by topic, each with a solution short enough to write on a whiteboard. Read the question, write your own answer first, then compare. In an interview the code is the smaller part of the answer, and the explanation of why it works is what is graded.

Language fundamentals

1. What does this print, and why? The question tests hoisting, which is the way JavaScript moves declarations to the top of their scope before running the code.

console.log(a); // undefined, var is hoisted and set to undefined var a = 1; console.log(b); // ReferenceError, b exists but cannot be read yet let b = 2;

A var declaration is hoisted with the value undefined, so the first line prints without error. A let or const declaration is also hoisted, but it cannot be read before its line runs, and that gap is called the temporal dead zone.

2. What is this inside a regular function and inside an arrow function?

const user = { name: "Ada", regular() { return this.name; }, arrow: () => this.name, }; user.regular(); // "Ada" user.arrow(); // undefined, arrow functions take this from outside const detached = user.regular; detached.call(user); // "Ada", call sets this explicitly

A regular function receives this from how it is called. An arrow function has no this of its own and uses the one from the scope where it was written.

3. Reverse a string without built-in helpers. No split, reverse, or join.

function reverse(str) { let out = ""; for (let i = str.length - 1; i >= 0; i--) out += str[i]; return out; } reverse("abc"); // "cba"

The usual follow-up is about emoji, which occupy two positions and get split by this loop.

Asynchronous JavaScript

4. In what order do these lines print? The question tests the event loop, which is the scheduler that runs callbacks after the current code finishes.

console.log("start"); setTimeout(() => console.log("timeout"), 0); Promise.resolve().then(() => console.log("promise")); console.log("end"); // start, end, promise, timeout

Synchronous code runs first. Promise callbacks go in the microtask queue, which is emptied before any timer callback runs, so "promise" prints before "timeout".

5. Write Promise.all by hand. It takes an array of promises and resolves with their results in the same order, or rejects on the first failure.

function promiseAll(promises) { return new Promise((resolve, reject) => { const results = new Array(promises.length); let remaining = promises.length; if (remaining === 0) return resolve(results); promises.forEach((p, i) => Promise.resolve(p).then((value) => { results[i] = value; if (--remaining === 0) resolve(results); }, reject)); }); }

Writing to results[i] rather than pushing keeps the order stable, because promises can finish in any sequence.

6. Write a debounce function. Debouncing delays a call until the caller has been quiet for a set time, which is how search boxes avoid one request per keystroke.

function debounce(fn, waitMs) { let timer; return function (...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), waitMs); }; } const onResize = debounce(() => console.log("resized"), 300);

Functions and closures

7. Write a counter factory. A closure is a function that keeps access to the variables of the scope where it was created, even after that scope has finished.

function makeCounter() { let count = 0; return () => ++count; } const next = makeCounter(); next(); // 1 next(); // 2

The variable count is private, because nothing outside makeCounter can reach it except the returned function.

8. Write a curry function. Currying turns a function of several arguments into a chain of functions that each take some of them.

function curry(fn) { return function curried(...args) { if (args.length >= fn.length) return fn(...args); return (...more) => curried(...args, ...more); }; } const add = curry((a, b, c) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6

9. Write a memoize function. Memoization saves the result of each call so a repeated argument returns the stored value instead of running the function again.

function memoize(fn) { const cache = new Map(); return (arg) => { if (!cache.has(arg)) cache.set(arg, fn(arg)); return cache.get(arg); }; } const fastSquare = memoize((n) => n * n);

The interviewer will ask about functions with several arguments, where the cache key must be built from all of them.

Arrays and objects

10. Flatten a nested array.

function flatten(arr) { return arr.reduce( (out, item) => out.concat(Array.isArray(item) ? flatten(item) : item), [] ); } flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]

Mention arr.flat(Infinity) as the built-in, then explain the recursive version, because the recursion is what is tested.

11. Deep clone an object. A shallow copy shares nested objects with the original, while a deep clone copies every level.

function deepClone(value) { if (value === null || typeof value !== "object") return value; if (Array.isArray(value)) return value.map(deepClone); const copy = {}; for (const key of Object.keys(value)) copy[key] = deepClone(value[key]); return copy; }

The built-in structuredClone also handles dates and maps. The usual follow-up is about circular references, which this version does not handle.

12. Remove duplicates from an array.

const nums = [3, 1, 3, 2, 1]; const unique = [...new Set(nums)]; // [3, 1, 2] const uniqueBy = (items, key) => { const seen = new Set(); return items.filter((item) => !seen.has(item[key]) && seen.add(item[key])); };

A Set keeps insertion order, so the first occurrence of each value survives. The second version handles objects, where equality has to be defined by a chosen field.

If you are new to JavaScript

The questions above assume you already write JavaScript daily. If you are still learning, start with the smaller exercises in What Javascript coding challenges are perfect for beginners?, and use the concept-ordered list in Best Coding Challenges for Beginners for the algorithm side.

How to Prepare

  • Explain before you type. For every question above, say what the output will be and why, then run the code to check.
  • Know which round asks these. Language questions appear in phone screens and pair-programming rounds. What type of coding questions will be asked in an interview? explains how they differ from algorithm rounds.
  • Cover the algorithm side separately. Grokking the Coding Interview teaches the patterns behind array, string, and tree questions, with every solution available in JavaScript.
  • Practice under time. A mock interview with a live interviewer shows whether you can explain the event loop while writing the code.
TAGS
Coding Interview
CONTRIBUTOR
Arslan Ahmad
Arslan Ahmad
ex-FAANG engineering manager and author or Grokking series.

GET YOUR FREE

Coding Questions Catalog

Design Gurus Newsletter - Latest from our Blog
Boost your coding skills with our essential coding questions catalog.
Take a step towards a better tech career now!
Explore Answers
How many hours do you work at OpenAI?
Why do I want to join Uber?
What Is the Zomato Android System Design Interview Like?
What candidates report about Zomato's Android coding and design rounds, and the app size, startup speed, and image memory topics its published engineering work raises.
What percentage of software engineers have no degree?
What is the easiest sorting algorithm to learn?
What Is the Shopee Interview Process Like? (Round by Round)
Candidates report an HR screen, an online assessment, one or two technical rounds, and a manager round, over about two to four weeks.
Related Courses
New
Grokking the AI System Design Interview course cover
Grokking the AI System Design Interview
Learn to design AI systems the way interviewers expect: classic ML products, LLM and RAG architectures, and agentic systems, all through the lens of the system design interview.
4.6
(3,192 learners)
Discounted price for Your Region

$98

Grokking the Coding Interview: Patterns for Coding Questions course cover
Grokking the Coding Interview: Patterns for Coding Questions
The 24 essential patterns behind every coding interview question. Available in Java, Python, JavaScript, C++, C#, and Go. The most comprehensive coding interview course with 543 lessons. A smarter alternative to grinding LeetCode.
4.6
Discounted price for Your Region

$197

Grokking Modern AI Fundamentals course cover
Grokking Modern AI Fundamentals
Master the fundamentals of AI today to lead the tech revolution of tomorrow.
4.1
Discounted price for Your Region

$72

Design Gurus logo
One-Stop Portal For Tech Interviews.
About Us
Our Team
Careers
Partners
Contact Us
Become Affiliate
Copyright © 2026 Design Gurus, LLC. All rights reserved.