Top 100 JavaScript Interview Questions
Top 100 JavaScript Interview Questions
Product companies
Startups
FAANG/frontend interviews
[Link]/backend interviews
React/Vue/Angular roles
Closures
Event Loop
Promises
Async/Await
Prototypes
Debounce/Throttle
Event Delegation
Memory leaks
Performance optimization
Custom polyfills
JavaScript internals
JavaScript Fundamentals
1. What is JavaScript?
The == operator checks only for value equality (performing automatic type conversion if
types differ), while the === operator performs strict equality, requiring both the value and
data type to be identical.
4. What is hoisting?
Hoisting is a JavaScript mechanism where variable and function declarations are moved to
the top of their scope during the compilation phase, before the code is executed. This means
you can use variables and functions before you actually declare them in your source code.
The Temporal Dead Zone refers to the period where a variable exists in a scope but cannot
be accessed until it is initialized. The TDZ starts from the beginning of the block until the
variable is declared and initialized.
Data Types String, Number, Boolean, Null, Undefined, Symbol, Big Object, Array, Functio
Int n
Storage Stored directly on the Stack Stored on the Heap;
stack stores a pointer
(reference)
Assignmen Copy by Value: New variable gets a real copy Copy by Reference:
t New variable points
to the same object
Type coercion is the automatic or implicit conversion of a value from one data type to
another (such as a string to a number).
Truthy and falsy are programming concepts used to evaluate whether a non-Boolean value
(like a string, number, or object) should be treated as true or false in conditional logic.
Falsy Values
Falsy values represent an empty or non-existent state. In languages like JavaScript and
Python, a limited, specific list of values evaluates to false:
Truthy Values
A truthy value is simply any value that is not on the falsy list. Whenever these values appear
in a condition, they evaluate to true:
Booleans: true
Objects & Arrays: Any object, function, or array, even if empty (e.g., {}, [])
undefined: Means a variable has been declared but not yet assigned a
value. It is the default state that JavaScript automatically gives to things that
haven't been set.
null: Is an intentional assignment by a developer to indicate that a variable
is deliberately empty or has no value
Global Scope: Variables declared outside of any function or block have global scope. They
can be accessed and modified from anywhere in your entire program.
Function (Local) Scope: Variables declared within a function are local to that function. They
cannot be accessed from outside the function where they were defined.
Block Scope: Introduced in ES6, variables declared with let and const inside a block (code
within {}) are restricted to that specific block. This applies to structures like if statements and
loops.
JavaScript uses lexical scoping, meaning the accessibility of variables is determined by their
position in the source code. Nested functions have access to variables declared in their outer
(parent) scopes.
Introduced in ES6, variables declared with let and const inside a block (code within {}) are
restricted to that specific block. This applies to structures like if statements and loops.
Variables declared within a function are local to that function. They cannot be accessed from
outside the function where they were defined.
First-class functions are a programming language feature where functions are treated like
any other variable or data type . In languages with this feature, you can assign functions to
variables, pass them as arguments to other functions, return them from functions, and store
them in data structures.
A callback function is a function passed into another function as an argument, which is then
executed (or "called back") by the outer function to complete a specific task or routine
Asynchronous Operations: They ensure that a block of code doesn't execute until a time-
consuming task (like fetching data from an API, reading a file, or waiting for a user to click a
button) has finished.
Event Handling: They let you define custom behavior that runs in response to a specific
event.
A higher-order function is a function that either takes one or more functions as arguments or
returns a function as its result.
Methods like .map(), .filter(), and .reduce() in JavaScript are classic higher-order functions
A closure is a function that remembers and accesses variables from its outer scope even
after the outer function has finished executing.
function createBankAccount(initialBalance) {
let balance = initialBalance; // Private variable
return {
balance += amount;
return balance;
},
};
function createCounter() {
return function () {
count++;
return count;
};
increment(); // 1
increment(); // 2
function memoizedExpensiveCalculation() {
};
Currying is used in JavaScript to break down complex function calls into smaller, more
manageable steps. It transforms a function with multiple arguments into a series of
functions, each taking a single argument.
Each function takes a single argument and returns another function until all arguments are
received.
// Normal Function
// function add(a, b) {
// return a + b;
// }
// [Link](add(2, 3));
// Function Currying
function add(a) {
return function(b) {
return a + b;
[Link](addTwo(4));
[Link](add(5)(4));
Function composition is the process of combining two or more functions to produce a new
function. It involves building a pipeline where the output of one function serves as the input
for the next.
Hoisting Fully Hoisted. You can call the Not Hoisted. You must define
function before it is defined in it before you can call it.
your code.
Syntax Examples:
An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs the exact
moment it is defined. It is a common design pattern primarily used to create a private, local
scope, which prevents variables and functions from polluting the global namespace.
javascript
(function() {
})();
Data Privacy: Variables declared inside the IIFE cannot be accessed from the outside,
keeping your implementation details hidden and secure.
Avoiding Naming Collisions: Since everything inside the IIFE is scoped locally, you can use
common variable names (like i or count) without worrying about overwriting global variables
of the same name.
Setup Logic: It is highly useful for initialization or setup code that you only need to run once
and do not need to call again
A pure function in JavaScript is a function that consistently returns the same output for the
same input and produces no observable side effects.
Predictability: They are easy to reason about because their behavior is isolated.
Testability: Since they don't depend on external state, you don't need complex setups or
mocks to unit test them.
Memoization: Because the same inputs always yield the same output, results can be cached
to improve performance.
Concurrency: They are safer to use in parallel environments because they don't share or
modify external data.
let timeout;
return function(...args) {
clearTimeout(timeout);
[Link](context, args);
}, wait);
};
High-frequency events can trigger functions hundreds of times per second, which causes
performance bottlenecks, browser lag (jank), or server overload. Throttling ensures smooth
operation while maintaining a responsive experience.
let inThrottle;
return function(...args) {
if (!inThrottle) {
};
}
43. Implement debounce function.
1. call()
The call() method invokes a function immediately and allows you to pass arguments to the
function one by one (comma-separated).
Use case: When you need to execute a function right away and know the exact arguments.
2. apply()
The apply() method also invokes a function immediately, but it takes all of its arguments as a
single array.
Use case: When you have an array of arguments and want to execute a function right away
(or when using variadic functions like [Link](null, myArray)).
3. bind()
The bind() method does not execute the function immediately. Instead, it creates a brand-
new function with a permanently locked this context that you can execute later.
Use case: When you need to pass a function as a callback or event handler, but want to
ensure that this retains the correct object context when it eventually runs.
Quick Comparison
this Binding Explicitly binds this to a specific Lexically inherits this from the
object at creation. surrounding scope.
Function Creates a new copy of an existing Defines a new function with a concise
Creation function with a fixed this. syntax.
Arguments Has its own arguments object. Does not have its
Object own arguments object (must use rest
parameters).
Re-binding Cannot be re-bound once a function this value can never be changed
is already bound. via call, apply, or bind.
1. Shallow Copy
When you create a shallow copy, the outer layer is a new object, but inner arrays or objects
point to the same memory addresses as the original.
When you create a deep copy, every level of the object structure is recursively cloned. The
new object is entirely isolated from the original.
Arrays
Async JavaScript
JavaScript Promises make handling asynchronous operations like API calls, file loading, or
time delays easier. Think of a Promise as a placeholder for a value that will be available in the
future. It can be in one of three states
Fulfilled: The task was completed successfully, and the result is available.
let number = 4;
});
checkEven
1. [Link]() Method
2. [Link]() Method
3. [Link]() Method
4. [Link]() Method
async/await is a modern programming feature that lets you write asynchronous, non-
blocking code in a clean, sequential manner. Instead of chaining complex callbacks
or .then() statements, it allows asynchronous operations to read and behave like traditional
synchronous code.
async: Placed before a function declaration, it ensures that the function automatically
returns a Promise.
await: Placed before a Promise inside an async function, it pauses the function's execution
until the Promise resolves or rejects, without freezing the main thread.
Under the hood, async/await is "syntactic sugar" built on top of JavaScript Promises. It allows
you to pause and resume function execution so that you can capture resolved values directly
into variables rather than passing them into callback functions.
function fetchUserData() {
return fetch('[Link]
.then(response => [Link]())
.then(data => [Link]([Link]))
.catch(error => [Link](error));
}
it allows for asynchronous, non-blocking execution, ensuring the main thread doesn't
freeze when handling slow operations
Call Stack: The primary thread where your synchronous code is executed one step at a time.
Web APIs: Background environments (managed by the browser or [Link]) that handle time-
consuming tasks like setTimeout or fetching data, so they don't block the stack.
Task Queues (Callback/Macrotask & Microtask): Holding areas where asynchronous tasks
wait once they are completed in the background.
1. Check the Stack: The event loop continually watches the Call Stack.
2. Execute Synchronous Code: Any immediate code is placed on the Call Stack and runs to
completion.
3. Handle Async: When an asynchronous function is called, it is handed off to the Web APIs.
4. Queue Tasks: Once the background task finishes (e.g., a timer expires), its callback function is
sent to one of the Task Queues.
5. Process the Queue: When the Call Stack is completely empty, the event loop moves the
waiting tasks from the queue onto the Call Stack to be executed.
Not all tasks wait in the same queue. There are two main types:
Microtask Queue: Has higher priority. Tasks like Promises are placed here and are executed
immediately after the current stack finishes, before moving on to any other queues.
Callback/Macrotask Queue: Tasks like setTimeout, setInterval, and I/O events are placed
here and are only executed after the Microtask Queue is completely empty.
Server Client-side only (Never Client-side only (Never Sent with every HTTP
Access sent to the server sent to the server request (can affect
automatically) automatically) performance)
Memory leaks in frontend apps occur when applications retain references to unused data,
preventing the browser's garbage collector from freeing up memory. This causes the app's
memory usage to continually grow, leading to sluggishness, frozen screens, and eventual
browser crashes. C
Global Variables: Creating accidental global variables (e.g., omitting let, const, or var in
JavaScript) or heavily relying on them, meaning they live for the entire lifecycle of the tab.
Closures: Keeping references to variables inside closures that live longer than the scope they
were created in.
Optimizing website performance involves improving page loading speeds and responsiveness
by reducing file sizes, streamlining server requests, and optimizing browser rendering. This
enhances user experience, boosts SEO, and increases conversions.
Asset Bundling: Combine multiple CSS and JavaScript files into fewer files to minimize HTTP
requests.
Remove Unused Code: Audit your codebase and third-party plugins to eliminate dead or
redundant code.
2. Media Management
Image Optimization: Compress images without noticeably losing quality and convert them
into modern, web-optimized formats like WebP or AVIF.
Lazy Loading: Delay the loading of images and videos located below the fold until the user
scrolls down to them.
Specify Dimensions: Always define width and height attributes for images and videos so the
browser can reserve exact space, preventing layout shifts.
Browser Caching: Instruct the user’s browser to store static files locally (like stylesheets and
logos) so they don't have to be downloaded on repeated visits.
Content Delivery Networks (CDNs): Route user requests through globally distributed servers
so your website's static files are delivered from a location geographically closest to the user.
Reduce Redirects: Limit HTTP redirects (like 301 and 302), as they generate additional
requests and slow down the initial page load.
4. Server-Side Improvements
Fast Hosting: Upgrade to high-performance hosting plans (like VPS or dedicated servers) that
offer sufficient bandwidth and resources.
Database Optimization: Clean up databases by clearing out spam comments, revisions, and
unused data, and set up indexing for faster query lookups.
Avoid Render-Blocking Scripts: Place critical CSS in the HTML header, and
use async or defer attributes on JavaScript files so the browser can display page content
without waiting for scripts to download.
Use Google PageSpeed Insights to test and evaluate your Core Web Vitals.
Use GTmetrix or WebPageTest to identify specific loading bottlenecks and track your
improvements over time.
Implement debounce
Implement throttle
Implement [Link]
Implement EventEmitter
Implement memoization
Implement currying
Infinite currying
Custom setTimeout
1. Closures
2. Event Loop
3. Promises
4. Async/Await
5. this keyword
6. Prototypes
7. Debounce/Throttle
8. call/apply/bind
9. [Link]
11. Polyfills