Javascript Interview
Javascript Interview
1. JavaScript Fundamentals
• Data Types and Variables (var, let, const):
◦ JavaScript has seven primitive data types: BigInt, Boolean, Number, Null,
String, Symbol, and Undefined
. It also has two compound data types: Object and Array
.
◦ The var, let, and const keywords are used for variable declaration
.
◦ var is function-scoped and can be re-declared and updated
.
◦ let is block-scoped, can be updated but not re-declared
. Variables declared with let are only accessible within the block where they are
declared and any nested blocks
.
◦ const is also block-scoped, but its value cannot be changed once assigned
. While its value cannot be reassigned, properties of an object declared with const
can be modified
.
◦ The choice between these keywords is crucial for clarity and preventing
confusion about variable scope
.
• Hoisting:
◦ Hoisting is JavaScript's default behavior where declarations (variables and
functions) are moved to the top of their respective scopes during compilation
.
◦ While var and function declarations are hoisted, their initializations are
not
. This means a var variable can be accessed before its declaration, but its value
will be undefined until the initialization line is reached
.
◦ let and const variables are also hoisted but are subject to the Temporal Dead
Zone (TDZ), meaning they cannot be accessed before their declaration and
initialization, otherwise a ReferenceError will occur
.
◦ Strict mode ("use strict") can prevent unintended hoisting behaviors by
throwing errors for undeclared variables
.
• Scope and Scope Chain:
◦ Scope determines the visibility or accessibility of variables during runtime
.
◦ Global scope variables are declared outside functions and are accessible
anywhere
.
◦ Local (or Function) scope variables are declared within a function and are
accessible only inside it
.
◦ Block scope applies to variables declared with let and const within curly
braces {} and are accessible only inside that block
.
◦ The Scope Chain is how JavaScript engines find variables: if a variable is
not found in the local scope, the engine looks in the outer scope, then the global
scope. A ReferenceError is thrown if not found globally
.
• this Keyword:
◦ this refers to the object it belongs to, and its value changes based on the
context in which a function is invoked
.
◦ Its value can be unpredictable in event handlers, asynchronous functions, or
when assigning functions to variables
.
◦ Methods like bind(), call(), or apply() explicitly set the this value
. Arrow functions lexically bind this, meaning they inherit this from their
surrounding scope
.
• == vs. ===:
◦ == (equality operator) compares values after coercing them to the same type
.
◦ === (strict equality operator) compares both value and type without coercion
.
◦ === is generally preferred for more accurate comparisons in real-world
applications
.
• null vs. undefined:
◦ null is an assignment value indicating that a variable points to no object or
represents a non-existent/empty value
.
◦ undefined means a variable has been declared but not assigned a value
.
◦ A "not defined" error occurs when a variable has not been declared at all
.
• Type Coercion:
◦ Type coercion is the automatic conversion of values from one data type to
another during certain operations or comparisons
.
◦ It can lead to unexpected results, especially with arithmetic or comparison
operators
.
◦ Explicit coercion (e.g., Number(a)) and implicit coercion (a * 1) exist
.
2. Functions & Asynchronous JavaScript
• Function Declarations vs. Expressions:
◦ Function declarations are hoisted and can be called before being defined
.
◦ Function expressions are assigned to a variable, are not hoisted, and must be
defined before being called
.
• Arrow Functions:
◦ Provide a shorter, more concise syntax for writing functions
.
◦ They lexically bind the this value, unlike traditional functions, making this
more predictable
.
• Immediately Invoked Function Expressions (IIFE):
◦ An IIFE is a function that executes immediately after being defined
.
◦ Used to create a local scope and avoid polluting the global namespace
.
• Callbacks and Callback Hell:
◦ A callback function is passed as an argument to another function and executed
later, often for asynchronous operations or event handling
.
◦ Callback hell describes deeply nested callbacks, making code hard to read and
debug (often called the "pyramid of doom")
.
• Promises:
◦ Represent the eventual completion or failure of an asynchronous operation and
its resulting value
.
◦ They provide better error handling and avoid callback hell by allowing
chaining
.
◦ A Promise can be in one of three states: pending, fulfilled, or rejected
.
◦ Promise.all() executes multiple promises concurrently and resolves only when
all are fulfilled, or rejects if any single one fails
. Promise.race() resolves or rejects as soon as one promise settles
.
• async/await:
◦ Offers a cleaner, more readable way to write asynchronous code than Promises,
allowing it to be written in a synchronous-like style
.
◦ Errors in async/await functions are handled using try-catch blocks
.
• Event Loop:
◦ The Event Loop is a continually running process that handles asynchronous
callbacks in JavaScript's single-threaded model
.
◦ It checks if the call stack is empty and then executes callbacks from the
event queue (or message queue)
.
◦ Microtasks (e.g., Promise resolutions) are processed after the current script
and before macrotasks (setTimeout, setInterval)
.
• Higher-Order Functions:
◦ Functions that can accept other functions as arguments or return functions as
their results
. This is possible because functions in JavaScript are first-class citizens
.
• Closures:
◦ A closure is a function that remembers and can access its outer scope
(lexical environment), even after the outer function has finished executing
.
◦ They are valuable for data hiding and encapsulation, creating private data
.
• Currying:
◦ Transforms a function with multiple arguments into a nested series of
functions, each taking a single argument
.
◦ Advantages include reusability, modularity, and specialization by breaking
down complex functions into smaller, more focused ones
.
• call(), apply(), and bind():
◦ These methods are used to control the this value and pass arguments to
functions
.
◦ call() invokes a function with a specific this value and arguments passed
individually
.
◦ apply() is similar to call(), but arguments are passed as an array
.
◦ bind() creates a new function with a specific this value and optional
arguments, but does not invoke it immediately
.
• Generators:
◦ Special functions that can be paused and resumed during their execution using
the yield keyword, allowing them to produce a sequence of values over time
.
3. Data Structures & Operations
• Arrays:
◦ An array is a data type that allows storing multiple values in a single
variable, accessible by numerical indices
.
◦ Common methods:
▪ map(): Transforms each item in an array, returning a new array
.
▪ filter(): Creates a new array with elements that pass a test
.
▪ reduce(): Reduces an array to a single value by applying a function to
each element
.
▪ forEach(): Executes a provided function once for each array element but
does not return a new array
.
▪ slice(): Gets a subset of an array from a start to an end index (end
index not included), without modifying the original array
.
▪ splice(): Used to add, remove, or replace elements in an array based on a
start index
.
▪ includes(): Checks if an array contains a certain value, returning a
boolean
.
▪ sort() and reverse(): Used to sort and reverse array elements
respectively
.
• Array-like Objects:
◦ Objects that have indexed elements and a length property, similar to arrays,
but lack array methods like push() or pop()
. Examples include arguments and HTMLCollection
.
◦ Can be converted to true arrays using Array.from(), the spread syntax (...),
or Array.prototype.slice.call()
.
• Object Manipulation:
◦ Objects are collections of properties (key-value pairs)
. Keys can be of any data type in Maps, but limited to strings/symbols in regular
objects
.
◦ Properties can be added, modified, or deleted using dot notation (obj.prop)
or bracket notation (obj['prop'])
. Bracket notation is necessary when the property name is stored in a variable
.
◦ Properties can be iterated using for...in loops, Object.keys() with
forEach(), or Object.values()
.
◦ Checking property existence can be done with the in operator or
hasOwnProperty() method
.
• Destructuring:
◦ Allows unpacking values from arrays or objects into distinct variables,
making code cleaner and easier to understand
.
• Shallow vs. Deep Copy:
◦ Shallow copy copies only the first level of an object, meaning nested objects
still share references
.
◦ Deep copy copies all levels, creating completely independent objects
. JSON.parse(JSON.stringify(obj)) is a common method for deep copying, though it
has limitations
.
◦ Objects can be merged using Object.assign() or the spread operator (...)
.
• Map and Set:
◦ Map stores key-value pairs where keys can be of any data type, and it
maintains insertion order
.
◦ Set is a collection of unique and ordered elements
.
• WeakMap and WeakSet:
◦ Collections that hold weak references to their elements (keys in WeakMap,
objects in WeakSet), meaning these references do not prevent garbage collection if
no other references exist to the objects
.
◦ Primarily used to prevent memory leaks when dealing with large objects
.
4. DOM Manipulation & Events
• Document Object Model (DOM):
◦ The DOM represents a web page as a tree-like structure, allowing JavaScript
to dynamically access and manipulate content and structure
. HTML is a markup language for developers, while the browser internally works with
the DOM
.
• DOM Selectors:
◦ Methods to get references to HTML elements: getElementById(),
getElementsByClassName(), getElementsByTagName(), querySelector(), and
querySelectorAll()
.
◦ getElementById() returns a single element by its unique ID
.
◦ getElementsByClassName() and getElementsByTagName() return HTMLCollection
(array-like objects) of matching elements
.
◦ querySelector() returns the first element matching a CSS selector
.
◦ querySelectorAll() returns a NodeList (array-like object) of all matching
elements
.
• Modifying and Creating DOM Elements:
◦ Elements' properties and attributes can be modified
. Styles can be added/removed using setProperty() or
classList.add()/remove()/toggle()
.
◦ New elements are typically created using createElement()
.
◦ cloneNode() creates a copy of an existing element
.
◦ createTextNode() creates a text node for existing elements
.
• Event Handling:
◦ The process of responding to user actions or other occurrences on a web page
.
◦ addEventListener() is used to attach an event name (e.g., 'click') and a
callback function (event handler) to an element
.
◦ removeEventListener() is used to detach an event handler
.
◦ The event object provides information about the event, including e.target
(the element where the event originated) and e.currentTarget (the element to which
the event listener is attached)
.
◦ Event Bubbling: Events start from the deepest element and propagate upwards
through the DOM hierarchy
.
◦ Event Capturing: Events are caught as they descend from the root to the
target element
.
◦ Event Delegation: Attaching a single event listener to a parent element to
handle events on its child elements, particularly useful for dynamic content and
memory efficiency
.
5. Error Handling & Debugging
• try-catch-finally:
◦ try-catch blocks are used to test a block of code for errors and handle
exceptions gracefully
.
◦ The finally block executes after try and catch blocks, regardless of whether
an exception was thrown or caught, making it suitable for resource cleanup
.
• throw Statement and Error Propagation:
◦ The throw statement stops the execution of the current function and passes
the error to the catch block of the calling function
.
◦ Error propagation refers to this process of an error bubbling up the call
stack until caught or until it reaches the global context, potentially terminating
the script
.
• Types of Errors:
◦ SyntaxError: Thrown when there's a parsing error in the code (e.g., a missing
bracket)
.
◦ ReferenceError: Occurs when a non-existent or undeclared variable is
referenced
.
◦ TypeError: Occurs when a value is not of the expected type (e.g., trying to
call a non-function)
.
◦ RangeError: Occurs when a number is outside an allowable range
.
◦ Logical errors: Occur when syntax is correct but the program's logic is
flawed, leading to incorrect output without error messages
.
• Debugging:
◦ The debugger keyword acts as a breakpoint, pausing code execution to allow
line-by-line inspection and error finding
.
◦ Best practices for error handling include using try-catch, descriptive error
messages, cleaning up resources, and avoiding empty catch blocks
.
6. ES6+ Features & Modern JavaScript
• Template Literals and String Interpolation:
◦ Provide a concise and readable way to create strings, including expressions,
multi-line strings, and string interpolation using backticks ( ) and ${expression}
.
• Spread (...) and Rest (...) Operators:
◦ Spread operator (...) allows an iterable (like an array) to be expanded in
places where zero or more arguments or elements are expected (e.g., array literals,
function calls, object merging)
.
◦ Rest parameter (...) syntax allows a function to accept an indefinite number
of arguments as an array
.
• Temporal Dead Zone (TDZ):
◦ The period between a let or const variable's declaration and its
initialization, during which accessing it results in a ReferenceError
.
• Optional Chaining (?.):
◦ Allows safely accessing nested properties of an object; evaluation stops and
returns undefined if a part of the path is null or undefined, preventing runtime
errors
.
• Private Properties (#):
◦ Introduced in ES2020, allows declaring private properties in classes using
the # symbol, accessible only from inside the class
.
• ES6 Modules:
◦ Allow for modular programming by exporting and importing values from/to
different files (import/export)
.
◦ Unlike older module systems (like CommonJS), ES6 modules undergo static
analysis, enabling optimizations like tree-shaking
.
◦ Dynamic imports (import()) allow loading modules asynchronously and on
demand, useful for code splitting
.
7. Performance & Optimization
• Debouncing and Throttling:
◦ Throttling limits a function's execution to once in a specified time frame
.
◦ Debouncing delays a function's execution until after a specified time has
elapsed since its last call
.
◦ Used to optimize performance for repetitive events (e.g., scrolling,
resizing, typing in a search bar)
.
• Memoization:
◦ An optimization technique that caches the results of expensive function calls
based on their inputs, returning the cached result for subsequent calls with the
same inputs
.
• Web Workers:
◦ Allow running JavaScript in a background thread, preventing blocking of the
main thread and keeping the user interface responsive
.
• Tree-shaking:
◦ A process in JavaScript build tools (like Webpack) that removes unused code
from bundles, reducing file size and improving load time
.
8. Design Patterns
• Module Pattern: Encapsulates privacy, state, and organization using closures,
helping to avoid global scope pollution
. The Revealing Module Pattern specifically hides implementation details while
exposing a public API
.
• Singleton Pattern: Ensures a class has only one instance and provides a global
point of access to it
.
• Observer Pattern: Allows an object (subject) to notify other objects (observers)
when its state changes, fundamental to event-driven programming
.
• Factory Pattern: Creates objects without specifying their exact class
.
9. Memory Management
• Garbage Collection:
◦ Automatic memory management where the JavaScript engine frees up memory used
by objects no longer in use (unreachable from the root)
.
◦ Can affect application performance if it happens frequently or takes a long
time, as it temporarily pauses script execution
.
• Memory Leaks:
◦ Occur when an application continuously uses more memory without releasing
unused memory
.
◦ Can be prevented by avoiding global variables, properly managing event
listeners, and carefully handling closures that might retain references to large
objects
.
◦ Tools like memory profiles and heap snapshots help debug memory issues
.
10. Tricky Concepts/Peculiarities
• Floating-Point Arithmetic Issues:
◦ JavaScript uses a double-precision floating-point format for numbers, which
can lead to precision issues in arithmetic calculations (e.g., 0.1 + 0.2 !== 0.3)
.
• Object Keys Coercion:
◦ When an object is used as a key in another object, JavaScript coerces the
object to a string ("[object Object]"), leading to potential unintended overwrites
if different objects coerce to the same string representation
.
• typeof null:
◦ A known peculiarity where typeof null returns "object", which is considered a
bug
.
These challenges and concepts are crucial in JavaScript interviews because they
test a candidate's foundational knowledge, their ability to debug and solve real-
world problems, optimize application performance, and write organized, scalable,
and secure code
. Interviews often go beyond simple definitions, asking for practical examples,
comparisons, and scenarios to gauge a deeper understanding.