Interview questions · Tech stack

JavaScript Coding Interview Questions & Answers (2026)

These interviews test core JavaScript concepts, problem‑solving ability, and code readability. Mastering fundamentals like closures, async patterns, and prototype inheritance, plus practicing algorithmic challenges, will help you demonstrate depth and confidence. Focus on clear explanations, optimal solutions, and edge‑case handling to stand out.

18 questions · updated Aug 29, 2026

Quick facts

Typical roundsPhone screen, live coding, system design, and take‑home assignment
Key topicsScope, closures, async/await, event loop, prototype chain, ES6+ features
Preferred languagesJavaScript (Node.js) or TypeScript, often with React or Express context
Success metricCorrect algorithm, clean code, and ability to discuss time/space trade‑offs

Questions

Beginner

Explain how closures work in JavaScript and give a simple example.

A closure is created when an inner function retains access to variables from its outer lexical scope even after the outer function has finished executing. The inner function forms a closure over those variables, allowing them to persist. For example, function makeCounter() { let count = 0; return function() { return ++count; }; } const counter = makeCounter(); counter(); // 1, counter(); // 2. The returned function keeps a reference to count, demonstrating closure behavior. Interviewers look for understanding of lexical scoping, memory retention, and typical use cases like data encapsulation.

function makeCounter(){let count=0;return function(){return ++count;};}
GoogleMicrosoftAmazon

What is the difference between == and === in JavaScript?

The == operator performs type coercion before comparing values, converting operands to a common type, which can lead to unintuitive results (e.g., 0 == '0' is true). The === operator, known as strict equality, compares both value and type without coercion, so 0 === '0' is false. Interviewers expect you to discuss why strict equality is preferred for predictable code and to illustrate edge cases such as null == undefined being true while null === undefined is false.

FacebookNetflix

How does the event loop handle asynchronous callbacks in JavaScript?

JavaScript runs on a single thread with a call stack and a task queue. When an asynchronous operation (e.g., setTimeout, fetch) completes, its callback is placed in the task queue. The event loop continuously checks if the call stack is empty; when it is, the next callback from the queue is pushed onto the stack and executed. This mechanism ensures non‑blocking behavior while preserving order. Interviewers look for clarity on microtasks vs. macrotasks and the role of promises in the queue.

AirbnbUber

What are the main differences between var, let, and const?

var is function‑scoped, hoisted to the top of its containing function, and can be re‑declared or reassigned. let and const are block‑scoped, introduced in ES6; let allows reassignment but not redeclaration, while const prohibits reassignment after initialization. Both let and const are hoisted but remain in a temporal dead zone until their declaration line is executed. Interviewers expect you to discuss hoisting, TDZ, and why const is preferred for immutable bindings.

LinkedInTwitter

Describe how prototypal inheritance works in JavaScript.

Every object has an internal [[Prototype]] reference pointing to another object. When accessing a property, JavaScript first looks on the object itself; if not found, it follows the prototype chain until the property is located or the chain ends at null. Functions used as constructors have a prototype property that becomes the [[Prototype]] of instances created with new. Interviewers want you to illustrate with a simple constructor function and explain how methods can be shared via the prototype to avoid duplication.

function Person(name){this.name=name;} Person.prototype.greet=function(){return `Hi ${this.name}`;}; const p=new Person('Alex'); p.greet();
Adobe

Intermediate

Implement a function to debounce another function.

Debouncing ensures a function runs only after a specified idle period, preventing excessive calls during rapid events like scrolling. The implementation returns a wrapper that clears any existing timer and sets a new one each invocation. When the timer expires, the original function executes with the latest arguments. Interviewers assess understanding of closures, timer handling, and practical performance benefits. Example code follows.

function debounce(fn, wait){let timeout;return function(...args){clearTimeout(timeout);timeout=setTimeout(()=>fn.apply(this,args),wait);};}
GoogleMicrosoft

Explain the difference between process.nextTick and setImmediate in Node.js.

Both schedule callbacks after the current operation, but process.nextTick queues callbacks to run before the event loop proceeds to the next phase, effectively giving them higher priority. setImmediate places callbacks in the check phase, which runs after I/O callbacks. This means nextTick can starve the event loop if used excessively, while setImmediate provides a more balanced approach. Interviewers look for knowledge of Node's phases and appropriate use cases.

AmazonNetflix

How would you shallow copy an object and why might you need a deep copy?

A shallow copy duplicates the top‑level properties but retains references to nested objects. You can use Object.assign({}, obj) or the spread operator {...obj}. A deep copy creates independent copies of all nested structures, preventing unintended side effects when mutating nested data. Deep copies can be achieved with JSON.parse(JSON.stringify(obj)) for simple data or with recursive functions for complex types. Interviewers expect you to discuss trade‑offs, performance, and when immutability matters.

const shallow={...original};
Facebook

Write a function that returns the nth Fibonacci number using memoization.

Memoization stores previously computed results to avoid redundant recursion, reducing exponential time to linear. The function defines a cache object; on each call, it checks the cache before computing recursively. This demonstrates understanding of closures, performance optimization, and recursion. The solution returns correct results for large n without stack overflow.

function fib(n, memo={}){if(n<2)return n;if(memo[n])return memo[n];return memo[n]=fib(n-1,memo)+fib(n-2,memo);} 
GoogleUber

What is the purpose of the async/await syntax, and how does it differ from using promises directly?

async/await provides syntactic sugar over promises, allowing asynchronous code to be written in a synchronous style. An async function returns a promise automatically, and await pauses execution until the promise resolves, handling both fulfillment and rejection with try/catch. Compared to chaining .then(), await reduces nesting, improves readability, and makes error handling more straightforward. Interviewers want you to discuss how the engine still uses promises under the hood and the importance of handling rejected promises.

MicrosoftAirbnb

Explain how the JavaScript garbage collector works and what kinds of memory leaks can occur.

Modern JavaScript engines use a generational, mark‑and‑sweep collector. Objects reachable from roots (global scope, stack, closures) are marked; unmarked objects are reclaimed. Common leaks include lingering references in closures, timers or event listeners that aren't removed, and accidental global variables. Understanding the difference between strong and weak references (WeakMap/WeakSet) helps prevent leaks. Interviewers look for awareness of how to profile memory and best practices for cleanup.

LinkedIn

Advanced

Implement a function that flattens a nested array of arbitrary depth.

Flattening requires recursion or iteration to traverse each element, concatenating non‑array values and recursively processing arrays. A depth‑first approach using Array.prototype.reduce works elegantly: the reducer checks if the current element is an array; if so, it concatenates the result of flattening that element; otherwise, it pushes the element. This solution handles any nesting level, demonstrates mastery of recursion, and respects immutability by returning a new array.

function flatten(arr){return arr.reduce((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val),[]);}
GoogleNetflix

What are the differences between call, apply, and bind methods?

All three methods set the this context for a function. call invokes the function immediately with arguments listed individually; apply does the same but expects arguments as an array. bind returns a new function with a permanently bound this and optional preset arguments, allowing later invocation. Interviewers expect you to illustrate use cases, such as borrowing methods (call/apply) and creating partially applied functions (bind).

MicrosoftFacebook

Describe how you would implement a custom event emitter in JavaScript.

A custom emitter maintains a map of event names to listener arrays. The API includes on(event, listener) to register, off(event, listener) to deregister, and emit(event, ...args) to invoke all listeners with provided arguments. Using closures to keep the listeners private ensures encapsulation. This pattern mirrors Node's EventEmitter and demonstrates understanding of pub/sub, memory management, and asynchronous flow.

function createEmitter(){const events={};return{on(e,l){(events[e]=events[e]||[]).push(l);},off(e,l){if(events[e])events[e]=events[e].filter(fn=>fn!==l);},emit(e,...a){if(events[e])events[e].forEach(fn=>fn(...a));}}}
Amazon

Explain the concept of a JavaScript Proxy and give an example use case.

A Proxy intercepts fundamental operations (property lookup, assignment, function invocation) on a target object via handler traps. This enables meta‑programming such as validation, lazy loading, or logging. For example, a validation proxy can enforce type constraints on property sets, throwing errors on invalid assignments. Interviewers look for understanding of trap signatures, performance considerations, and practical scenarios like observable state management.

GoogleNetflix

How does tail call optimization work in JavaScript, and is it reliable across browsers?

Tail call optimization (TCO) reuses the current stack frame for a function call when the call is in tail position, preventing stack growth. ES6 mandates proper tail calls, but only Safari currently implements it fully; other browsers ignore it for safety. To write TCO‑safe code, ensure the recursive call is the last operation and that no additional work follows. Interviewers assess awareness of spec vs. implementation and fallback strategies like iterative loops.

Apple

What is the difference between a shallow copy and a deep copy of an object, and how would you implement a deep copy without external libraries?

A shallow copy duplicates only top‑level properties, preserving references to nested objects, while a deep copy recursively clones every level, producing independent structures. A custom deep copy can be built using a recursive function that checks the type of each property; for objects and arrays, it creates a new instance and copies each key/value pair, handling circular references via a WeakMap. This demonstrates mastery of recursion, type checking, and memory safety.

function deepClone(obj, map=new WeakMap()){if(obj===null||typeof obj!=='object')return obj; if(map.has(obj))return map.get(obj); const copy=Array.isArray(obj)?[]:{}; map.set(obj,copy); for(const key in obj){if(Object.hasOwnProperty.call(obj,key))copy[key]=deepClone(obj[key],map);} return copy;}
MicrosoftAmazon

Explain how the spread operator works with iterables and objects, and mention any limitations.

The spread syntax ... expands an iterable's elements into a new array or an object's own enumerable properties into a new object. For arrays, it creates a shallow copy and can concatenate multiple iterables. For objects, it copies own properties, excluding prototype chain and non‑enumerable symbols. Limitations include inability to spread non‑iterables, loss of getters/setters, and shallow copying of nested objects. Interviewers expect you to discuss these nuances and when to prefer Object.assign or structuredClone.

Facebook

Common mistakes

  • Using var for block‑scoped variables, leading to unexpected hoisting.
  • Neglecting to handle promise rejections, causing unhandled promise errors.
  • Writing recursive solutions without memoization, resulting in exponential time.
  • Modifying objects directly instead of returning new copies, breaking immutability.
  • Forgetting to remove event listeners or timers, causing memory leaks.

Study plan

  1. Review core language concepts: scope, closures, this binding, and prototype chain.
  2. Practice async patterns: callbacks, promises, async/await, and event loop nuances.
  3. Solve algorithmic problems focusing on array manipulation, recursion, and memoization.
  4. Implement common utilities (debounce, throttle, deep clone) to solidify patterns.
  5. Mock interview sessions with timed live coding and post‑mortem analysis.

FAQ

How many coding questions are typically asked in a JavaScript interview?

Most companies ask 2–3 coding problems per round, covering data structures, algorithms, and language‑specific features. Some may add a fourth system‑design or take‑home task, but the total stays under five per interview day.

Should I use TypeScript instead of plain JavaScript for coding interviews?

If the role explicitly mentions TypeScript, using it can showcase type‑safety skills. Otherwise, stick to plain JavaScript to avoid syntax errors and focus on core concepts the interviewer expects.

What is the best way to explain my solution during a live coding session?

State the problem briefly, outline the high‑level approach, discuss time and space complexity, write clean code with meaningful names, and narrate each step while handling edge cases. End with a quick test run.

How important is knowledge of the JavaScript event loop for senior positions?

Very important. Senior engineers must diagnose performance bottlenecks, understand micro‑ vs. macro‑tasks, and design reliable async flows. Demonstrating deep event‑loop knowledge signals readiness for complex production code.

Can I use built‑in functions like Array.prototype.flat in my interview answers?

Yes, but be prepared to explain how they work internally. Interviewers may ask you to implement the same functionality without built‑ins to assess algorithmic thinking.

Related

Ready for your next interview?

Download MiPrep AI. Load your resume and the job description. Show up ready.

Free tier · No credit card · macOS 14+ · Windows 10+

Free tier · No credit card · Runs on your Mac or Windows machine