Skip to main content

JavaScript Interview Cheat Sheet

Top 50 interview questions with concise answers. Print this page or save as PDF for offline study.

View All JavaScript Questions

1. What is JavaScript and where is it used?

JavaScript is a dynamic, interpreted programming language originally designed for the browser. Today it runs everywhere — browsers (DOM manipulation, SPAs), servers (Node.js), mobile (React Native), and desktop (Electron). It's the only language that runs natively in every browser, making it the universal language of the web.

2. Difference between var, let, and const.

var is function-scoped and hoisted — can be redeclared, accessible before declaration (as undefined). let is block-scoped, not hoisted in a usable way, can be reassigned but not redeclared. const is block-scoped, can't be reassigned. Prefer const by default, use let when you need to reassign, avoid var in modern code.

3. What is hoisting in JavaScript?

Hoisting moves declarations to the top of their scope during compile time — before code runs. var declarations and function declarations are hoisted. var is initialized as undefined; function declarations are fully hoisted (callable before they appear). let and const are hoisted but not initialized — accessing them before declaration throws a ReferenceError (temporal dead zone).

4. Difference between synchronous and asynchronous execution.

Synchronous: each operation runs in order, one at a time — the next line waits for the current one to finish. Asynchronous: an operation starts and the code continues without waiting — when the operation completes, a callback or Promise resolves. JavaScript is single-threaded, so async is essential for I/O (network, file) without blocking the main thread.

5. What is a closure?

A closure is a function that remembers the variables from its outer scope even after the outer function has returned. The inner function "closes over" those variables. Common use: factory functions, data privacy (like private variables), and callbacks that need access to loop variables. Every function in JavaScript is a closure.

6. What are data types in JavaScript?

JavaScript has: Primitive types — string, number, bigint, boolean, null, undefined, symbol. And Object type — including arrays, functions, dates, and plain objects. Primitives are immutable and compared by value. Objects are compared by reference — two separate objects with the same content are not equal.

7. Difference between == and ===.

== does loose equality with type coercion — "5" == 5 is true because JS converts the string to a number. === does strict equality with no coercion — "5" === 5 is false because types differ. Always use === in modern code to avoid the subtle bugs that type coercion introduces.

8. What is the event loop?

The event loop is JavaScript's concurrency mechanism. It continuously checks: is the call stack empty? If yes, take the next task from the callback queue (macrotasks) or microtask queue (Promises). Microtasks run before macrotasks. This single-threaded loop is how JS handles async operations without blocking.

9. Difference between null and undefined.

null is an intentional absence of value — you explicitly set it. undefined means a variable was declared but not yet assigned, or a function returns nothing, or an object property doesn't exist. typeof null is "object" (a famous JS bug). typeof undefined is "undefined". Both are falsy.

10. What are first-class functions?

First-class functions means functions are values in JavaScript — they can be stored in variables, passed as arguments, returned from other functions, and put in arrays or objects. This enables higher-order functions, callbacks, and functional programming patterns. It's what makes setTimeout(fn, 1000) work — fn is just a value.

11. Difference between function declaration and function expression.

Function declaration: function greet() {} — hoisted completely, can be called before it's defined in the file. Function expression: const greet = function() {} — not hoisted, only available after the assignment. Arrow functions are expressions too. Declarations are good for named utilities; expressions are better for callbacks and closures.

12. What is the this keyword?

this refers to the context in which a function is called. In a method: this is the object. In a regular function: this is window (or undefined in strict mode). In arrow functions: this is inherited from the enclosing scope (lexical this). In event handlers: this is the element. The value of this is determined by how the function is invoked, not where it's defined.

13. Difference between call, apply, and bind.

All three invoke a function with a specific this value. call(thisArg, arg1, arg2): invokes immediately with individual args. apply(thisArg, [args]): invokes immediately with args as an array. bind(thisArg, arg1): returns a new function with this permanently bound — call it later. Use bind for event handlers and callbacks where this would otherwise be lost.

14. What is prototype in JavaScript?

Every JavaScript object has a prototype — an object it inherits from. When you access a property, JS looks at the object first, then follows the prototype chain upward until it finds it or reaches null. Array.prototype has push, map, filter. Object.prototype has toString, hasOwnProperty. This chain is how inheritance works in JS.

15. Difference between ES5 and ES6.

ES6 (ES2015) added: let/const, arrow functions, template literals, destructuring, default parameters, rest/spread operators, classes, Promises, modules (import/export), Map/Set, Symbol, generators, and iterators. ES5 used var, function expressions, string concatenation, and no native module system. ES6 made JavaScript dramatically more expressive and modern.

16. What are promises?

A Promise represents the eventual result of an async operation — either resolved (success with a value) or rejected (failure with a reason). It avoids callback hell by enabling .then()/.catch() chaining. A Promise starts pending and settles exactly once. Promises are the foundation of async/await.

17. Explain async/await.

async/await is syntactic sugar over Promises. An async function always returns a Promise. await pauses execution inside the async function until the Promise resolves — without blocking the thread. Error handling uses try/catch instead of .catch(). It makes async code read like synchronous code — much cleaner than nested .then() chains.

18. Difference between shallow copy and deep copy.

Shallow copy copies only the top-level properties — nested objects still share the same reference. const copy = {...original} is shallow. Deep copy recursively copies all nested objects — structuredClone(original) or JSON.parse(JSON.stringify(original)) creates fully independent copies. Use deep copy when you need to modify nested data without affecting the original.

19. What is the difference between let inside and outside loops?

let inside a loop creates a new binding for each iteration — closures inside the loop capture their own independent copy of the variable. var inside a loop shares one variable across all iterations — closures capture the same reference. Classic bug: setTimeout inside a for-var loop all see the final value. for-let doesn't have this problem.

20. Explain event delegation.

Event delegation attaches one event listener to a parent element instead of individual listeners on every child. The event bubbles up from the clicked child to the parent listener. The listener checks event.target to determine which child was clicked. More efficient for dynamic lists — no need to add/remove listeners as items are added or removed.

21. What is the difference between function scope and block scope?

Function scope: variables declared with var are accessible anywhere within the containing function, regardless of the block (if, for) they're in. Block scope: variables declared with let or const are only accessible within the {} block they're in. Block scope prevents accidental variable reuse across if/for blocks and eliminates many var-related bugs.

22. Explain closures with real-world usage.

Closures in real use: a counter factory function returns a function that increments a private count variable — each call creates a new independent counter. Memoization stores results in a closed-over cache object. Module patterns use closures to create private state accessible only through exposed functions. Event handlers close over component state in React hooks.

23. What is the DOM and how does JavaScript interact with it?

The DOM (Document Object Model) is a tree of objects representing the HTML page. JavaScript interacts with it via document.querySelector(), element.textContent, element.style, element.addEventListener(). Every HTML element becomes a node in the tree. JS reads, modifies, adds, and removes nodes to make pages dynamic without a full reload.

24. Explain event bubbling and capturing.

Event bubbling: an event fires on the target element, then bubbles up through parent elements to the root. Event capturing: the event starts at the root and travels down to the target before bubbling up. addEventListener(event, handler, true) uses capturing phase. Default is bubbling. stopPropagation() prevents the event from continuing up or down the chain.

25. Difference between innerHTML, innerText, and textContent.

innerHTML: gets/sets HTML content — can include tags, but is a security risk (XSS) if set from user input. innerText: gets/sets visible text only — respects CSS visibility and triggers reflow. textContent: gets/sets all text content (including hidden) — doesn't trigger reflow, safer and faster than innerText. Prefer textContent for setting plain text.

26. Explain template literals.

Template literals use backticks (`) instead of quotes and allow: multi-line strings (no \\n needed), string interpolation (${expression} is evaluated inline), and tagged templates (a function processes the template). They replace string concatenation ("Hello " + name) with clean, readable `Hello ${name}` syntax.

27. What are arrow functions and how do they differ from regular functions?

Arrow functions: shorter syntax, no own this (inherit from enclosing scope), no arguments object, can't be used as constructors. Regular functions: have their own this (determined by call context), have arguments object, can be constructors. Use arrow functions for callbacks and methods that don't need their own this; regular functions for methods that do.

28. Explain higher-order functions.

Higher-order functions take other functions as arguments or return functions. Built-in examples: map(fn), filter(fn), reduce(fn), forEach(fn). They enable functional programming patterns — composing behavior without loops. A function like debounce(fn, delay) is a higher-order function that returns a new function wrapping fn with delayed execution.

29. What is the difference between map, forEach, and filter?

map: returns a new array with each element transformed by the callback. filter: returns a new array with only elements where callback returns true. forEach: just iterates — no return value, no new array. map and filter are chainable; forEach is for side effects. All three don't mutate the original array.

30. Explain setTimeout vs setInterval.

setTimeout(fn, ms): calls fn once after ms milliseconds. setInterval(fn, ms): calls fn repeatedly every ms milliseconds. Both are async — they don't block. The actual delay may be longer than specified (minimum is 0ms, actual depends on event loop state). Always clearInterval(id) to stop a repeating interval, or it runs forever.

31. What is the difference between synchronous and asynchronous DOM manipulation?

Synchronous DOM manipulation (direct writes) blocks rendering — the browser can't paint until the JS finishes. Asynchronous DOM manipulation (via requestAnimationFrame or setTimeout(0)) defers the change to the next paint cycle, keeping the UI responsive. For smooth animations, always use requestAnimationFrame — it's synchronized with the browser's display refresh rate.

32. Explain promises and chaining.

Promise chaining: fetch(url).then(r => r.json()).then(data => process(data)).catch(err => handleError(err)). Each .then() receives the resolved value of the previous Promise. .catch() at the end handles any rejection in the chain. Return a value from .then() to pass it to the next link; return a Promise to wait for it.

33. What are the browser storage options in JavaScript?

localStorage: persists data across browser sessions (survives tab close), domain-scoped, ~5MB, synchronous API. sessionStorage: same API but cleared when the tab closes. Cookies: small (~4KB), sent with every HTTP request (good for auth tokens), can have expiry. IndexedDB: full client-side database — async, large storage, good for complex offline apps.

34. Difference between synchronous and asynchronous XHR/fetch.

Synchronous XHR blocks the main thread until the server responds — freezes the page. Asynchronous XHR/fetch is non-blocking — the code continues and a callback/Promise fires when the response arrives. Never use synchronous XHR in production. fetch() is the modern, Promise-based replacement for XHR — cleaner API and supports async/await.

35. How do you handle cross-origin requests?

Browsers enforce Same-Origin Policy — your page at domain-a.com can't fetch from domain-b.com without server permission. CORS (Cross-Origin Resource Sharing) headers on the server grant permission: Access-Control-Allow-Origin: * (or specific domain). Preflight OPTIONS requests check permissions for non-simple requests. You can't bypass CORS from the browser — the server must allow it.

36. Explain event delegation and its benefits.

Attach one listener to the parent (e.g., a ul) instead of one per child (each li). When a child is clicked, the event bubbles to the parent listener. Use event.target to identify which child triggered it. Benefits: fewer listeners (better memory), handles dynamically added children automatically, cleaner code for large lists.

37. Difference between call, apply, and bind.

call(thisArg, arg1, arg2) and apply(thisArg, [arg1, arg2]) both invoke immediately — call takes args individually, apply takes an array. bind(thisArg) returns a new function permanently bound to that this — not invoked immediately. Use: call/apply for method borrowing, bind for event listeners where this would otherwise be wrong.

38. Difference between == and ===.

== coerces types before comparing — false == 0 is true, "" == 0 is true, null == undefined is true. === compares type AND value with no coercion — false === 0 is false. Always use === to avoid unexpected coercion. The only common use of == is null == undefined when you want to check for both in one expression.

39. Difference between null and undefined.

undefined: variable declared but no value assigned, or missing function return, or missing object property. null: explicitly assigned to mean "no value" — intentional emptiness. typeof undefined is "undefined"; typeof null is "object" (historical bug). null === undefined is false; null == undefined is true.

40. What are IIFEs (Immediately Invoked Function Expressions)?

An IIFE is a function that defines and calls itself immediately: (function() { ... })(). It creates a private scope — variables inside don't pollute the global scope. Before ES6 modules, IIFEs were the standard way to encapsulate code. Now replaced by ES modules and block scoping with let/const, but still useful for immediate initialization.

41. Explain ES6 modules and their benefits.

ES6 modules use import/export to share code between files. Each module has its own scope — no global namespace pollution. Imports are static (analyzable at parse time), enabling tree-shaking. The browser loads them with