JavaScript Core
Fundamentals
What are the different data types in JavaScript?
Primitive types (immutable, stored by value):
stringnumber(includes integers, floats,Infinity,NaN)bigint(for large integers)booleanundefinednullsymbol(unique identifiers)
Reference types (mutable, stored by reference):
object(includes arrays, functions, dates, etc.)
What problems does this solve?
- Prevents unintended memory mutations by understanding how primitive vs reference types are passed around.
- Eliminates subtle bugs where object references are shared unexpectedly across components or functions.
- Ensures developers allocate the correct heap vs stack memory conceptually when building large state machines.
What is the difference between == and ===?
==(loose equality): Compares values after type coercion.===(strict equality): Compares values AND types without coercion.
Best practice: Always use === to avoid unexpected behavior.
What problems does this solve?
- Eliminates silent type coercion bugs where unexpected values evaluate to true (e.g., `[] == false`).
- Forces deliberate type casting (like `Number(val) === 5`), making code explicitly readable and strict.
- Considerably lowers the cognitive load of tracking the abstract equality comparison algorithm in edge cases.
What is Hoisting?
JavaScript moves declarations to the top of their scope before execution.
Variables:
Functions:
let/const are hoisted but remain in the "Temporal Dead Zone" until initialization.
What problems does this solve?
- Explains why legacy `var` variables might be `undefined` instead of throwing ReferenceErrors when accessed early.
- Clarifies why standard `function() {}` declarations can safely be called at the very top of a file before their strict definition.
- Teaches developers how the JavaScript engine actually parses and physically moves memory allocations during the compilation phase.
What is the Temporal Dead Zone (TDZ)?
The period between entering a scope and the variable declaration being processed. Accessing let/const variables in TDZ throws ReferenceError.
What problems does this solve?
- Enforces clean coding standards by physically preventing the use of `let` or `const` variables before they are initialized.
- Safeguards against "temporal" scope bugs where a variable shadows a global scope but hasn't been assigned yet.
- Forces developers to define their variables at the very top of the block scope, improving code readability.
What is the difference between var, let, and const?
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Yes (undefined) | Yes (TDZ) | Yes (TDZ) |
| Reassignment | ✅ | ✅ | ❌ |
| Redeclaration | ✅ | ❌ | ❌ |
What problems does this solve?
- Replaces unpredictable, function-scoped `var` bindings with strictly Block-Scoped invariants.
- `const` strongly broadcasts intent that a primitive binding should NEVER change, preventing accidental re-assignment bugs.
- `let` safely limits temporary looping variables (like `i`) exclusively to within their `for` loops rather than leaking outwards.
What is Scope and what are the different types?
Scope determines variable accessibility.
Types:
- Global Scope: Accessible everywhere
- Function Scope: Accessible within the function
- Block Scope: Accessible within
{}(let/const) - Module Scope: Accessible within the module
What problems does this solve?
- Solves variable collisions where multiple scripts or functions accidentally try to write to the same `data` variable name.
- Allows deep memory optimization via Garbage Collection (once a function block finishes, its local scoped memory is freed).
- Provides the mechanical foundation for Encapsulation so developers can hide private data away from the Global object.
Functions & Closures
What is a Closure?
A function that retains access to its outer scope even after the outer function has returned.
Use cases:
- Data privacy/encapsulation
- Function factories
- Maintaining state in callbacks
- Currying
What problems does this solve?
- Provides native Data Privacy by mimicking 'private' variables before ES6 classes existed (e.g., a counter where the `count` is inaccessible).
- Allows for function factories where inner functions "remember" the specific configuration variables they were spawned with.
- Preserves specific scope data asynchronously, ensuring `setTimeout` or event listeners still have exact access to their initial creation variables.
What is the difference between function declarations and function expressions?
Function Declaration:
Function Expression:
Named Function Expression:
What problems does this solve?
- Function Expressions solve the problem of assigning functions as standard values passed dynamically into arrays, objects, or callbacks.
- Named Function Expressions provide explicit internal references, allowing anonymous callbacks to recursively call themselves safely.
- Function declarations solve code-ordering preferences, allowing developers to write their main execution logic safely at the top of a file.
What are Arrow Functions and how are they different?
Concise syntax with different this behavior.
Differences from regular functions:
| Feature | Regular Function | Arrow Function |
|---|---|---|
this binding | Dynamic | Lexical (inherits from parent) |
arguments | Has it | Doesn't have it |
| Constructor | Can use new | Cannot use new |
| Hoisting | Declarations hoisted | Never hoisted |
What problems does this solve?
- Permanently binds the `this` context lexically to where the function is defined, eliminating the need for `const self = this` hacks.
- Majorly reduces boilerplate syntax for short mapping/filtering operations by allowing implicit returns (e.g., `arr.map(x => x * 2)`).
- Prevents accidental usage as Constructor functions, as arrow functions securely lack a `prototype` object entirely.
Explain this in JavaScript.
this refers to the context in which a function is called.
What problems does this solve?
- Allows a single reusable function to operate dynamically across multiple different object contexts depending on how it's executed.
- Underpins the entirety of Prototypes and Classes, giving methods a dynamic reference to the exact instance currently invoking them.
- Provides isolation context for Event Listeners, allowing standard DOM `click` handlers to natively reference the target trigger element.
What are call, apply, and bind?
Methods to explicitly set this.
What problems does this solve?
- Allows you to forcefully "borrow" a method from one object and run it against completely foreign data without duplicating the code.
- `bind` solves asynchronous context loss, letting you pass class methods into a `setTimeout` without ripping away their inner `this` bindings.
- `apply` specifically solved the historic problem of passing an array of dynamic elements into functions that only accepted spread arguments (like `Math.max()`).
What is Currying?
Transforming a function with multiple arguments into a sequence of functions taking one argument each.
What problems does this solve?
- Allows for powerful 'Partial Application', letting you configure a base function once and reuse the pre-configured version repeatedly.
- Transforms multi-argument APIs into single-argument pipelines, unlocking Advanced Functional Programming compositions.
- Delays heavy execution computations safely until the final mandatory argument is finally provided.
Objects & Prototypes
What is Prototypal Inheritance?
Objects inherit properties and methods from other objects via the prototype chain.
Prototype chain:
What problems does this solve?
- Prevents massive memory bloat by allowing millions of object instances to share a single copy of methods in memory rather than duplicating them.
- Serves as the internal architectural foundation for extending built-in objects (like Arrays or Strings) globally.
- Allows dynamic runtime inheritance chains where objects can inherit properties from other live objects, rather than static class blueprints.
What is the difference between __proto__ and prototype?
prototype: Property of constructor functions. Defines what instances will inherit.__proto__: Property of all objects. Points to the object's prototype.
What problems does this solve?
- Clarifies the strict divide between the literal blueprint (`prototype`) and the live instance linkage pointer (`__proto__`).
- Understanding the difference is critical to safely polyfilling older browsers without destroying existing instance chains.
- Prevents massive performance degradation caused by accidentally mutating `__proto__` directly during runtime operations.
What are ES6 Classes?
Syntactic sugar over prototypal inheritance.
What problems does this solve?
- Standardizes object-oriented inheritance syntax, eliminating the messy, verbose historic `Object.setPrototypeOf` boilerplate patterns.
- Provides clean syntactic scaffolding for static methods, getters, setters, and explicit `super()` parent constructor execution.
- Lowers the onboarding complexity for developers migrating into JavaScript from strictly typed OOP languages like Java or C#.
What is Object.create() vs new?
Both create objects but differently:
What new does:
- Creates empty object
- Links
__proto__to constructor'sprototype - Binds
thisto new object - Returns the object (unless constructor returns object)
What problems does this solve?
- Allows developers to manually construct raw prototype delegation chains without being forced to execute a Constructor initialization function.
- Object.create(null) safely generates "pure" dictionary mapping objects that possess zero inherited baseline properties (like `hasOwnProperty`).
- Separates the inheritance definition entirely from the instantiation execution flow.
How do you copy objects (shallow vs deep)?
Shallow copy (nested objects are still references):
Deep copy:
What problems does this solve?
- Prevents catastrophic bugs where modifying nested array state in a React component accidentally mutates the historic state store.
- Separates network API payloads from local UI component state editing memory blocks.
- Clarifies the exact depth boundaries of spread operators `...` versus proper recursive structural cloning.
Asynchronous JavaScript
What is the Event Loop?
The mechanism that handles async operations in JavaScript's single-threaded environment.
What problems does this solve?
- Solves the fundamental physical disconnect between JavaScript's single-threaded nature and asynchronous operations like network requests.
- Ensures heavy operations (like reading a 10GB file) never freeze the UI by delegating them to background APIs and tracking their return.
- Dictates the strict execution prioritization of Callbacks, Promises, and DOM rendering repaints.
What is the difference between Microtasks and Macrotasks?
| Microtasks | Macrotasks |
|---|---|
| Promise callbacks | setTimeout |
| queueMicrotask() | setInterval |
| MutationObserver | setImmediate (Node) |
| I/O callbacks | |
| UI rendering |
Execution order:
- Complete current synchronous code
- Execute ALL microtasks
- Execute ONE macrotask
- Repeat
What problems does this solve?
- Prevents Promise chains from being randomly interrupted by heavy UI tasks or generic `setTimeout` renders.
- Always executes `MutationObserver` and Promise Microtasks immediately before the next rendering phase for visual consistency.
- Provides developers granular control over breaking up long, CPU-heavy tasks without blocking immediate user interactions.
What is a Promise?
An object representing the eventual completion (or failure) of an async operation.
States: Pending → Fulfilled OR Rejected
What problems does this solve?
- Solves 'Inversion of Control' by handing back a controllable proxy object instead of requiring developers to surrender their callback blindly to third parties.
- Flattens and standardizes deeply nested pyramid callback chains into readable, vertical `.then()` sequential pipelines.
- Provides unified, singular `.catch()` blocks capable of capturing scattered errors from anywhere within a chained sequence.
What is async/await?
Syntactic sugar for Promises, making async code look synchronous.
What problems does this solve?
- Enables reading asynchronous operations sequentially top-to-bottom precisely as if they were synchronous blocking code.
- Allows developers to natively wrap async API calls inside standard, highly intuitive `try/catch` layout blocks.
- Eliminates the chaotic scoping boundaries and variable tracking complexities inherently found within disjointed `.then()` callback jumps.
What is a Callback and what is Callback Hell?
A callback is a function passed as an argument to be executed later.
Callback Hell: Deeply nested callbacks that are hard to read/maintain.
What problems does this solve?
- Resolves the 'Pyramid of Doom' where code deeply nests to the right, becoming physically unreadable and difficult to source-control diff.
- Fixes "Callback Hell" where multiple distinct operations executing in parallel cannot smoothly coordinate their final exit states.
- Moves developers away from legacy codebases lacking proper Error trapping where a single nested callback failure silently crashed everything.
Arrays & Iteration
What are the most important Array methods?
Mutating methods:
Non-mutating (return new array):
What problems does this solve?
- Replaces verbose and error-prone standard `for` loops with strictly semantic, declarative one-liners.
- Ensures pure functional data transformations by guaranteeing original referenced arrays remain unmutated.
- Standardizes extremely common algorithms (sorting, locating indices, checking 'some' vs 'every' element) across all global codebases.
What is the difference between map, filter, and reduce?
What problems does this solve?
- Separates logic concerns: mapping scales values 1:1, filtering securely drops values, and reducing mathematically collapses values.
- Chaining these declarative functions eliminates the need to create massive, bloated temporary wrapper arrays inside loops.
- Provides highly predictable and independently testable transformation blocks compared to writing monolithic conditional `while` loops.
What is the difference between for...in and for...of?
for...in: Iterates over enumerable property keys (for objects)for...of: Iterates over iterable values (for arrays, strings, etc.)
What problems does this solve?
- Solves the ambiguity of looping architectures: `for...in` strictly enumerates over String Keys (like Object properties), `for...of` strictly consumes values (like Iterables).
- Prevents accidental iteration over inherited prototype chain properties which often broke legacy array looping.
- Provides universal consumption mechanics for modern data structures like Sets, Maps, and NodeLists.
ES6+ Features
What is Destructuring?
Extract values from arrays/objects into variables.
What problems does this solve?
- Eliminates massive blocks of repetitive `const name = obj.name` boilerplate property extraction.
- Allows components to instantly grab precisely the deep nested variables they need right inside the function argument signature interface.
- Enables assigning safe fallback default values instantly if dynamic API responses return missing fields.
What is the Spread Operator and Rest Parameters?
Spread (...): Expands iterables/objects.
Rest (...): Collects remaining arguments.
What problems does this solve?
- Replaces ugly `.concat()` methods by smoothly blowing out array elements natively into other arrays or new physical object clones.
- Rest parameters completely deprecate the unpredictable `arguments` object by cleanly capturing dynamic unlimited parameters into a real Array.
- Allows separating arbitrary specific properties from an object while dynamically sweeping all remaining unknown properties into a generic bucket.
What are Template Literals?
Strings with embedded expressions and multi-line support.
What problems does this solve?
- Eliminates chaotic, untrackable string concatenation like `"Hello " + name + ", it is " + time`.
- Natively supports elegant multi-line string text blocks without resorting to messy `\n` escaping.
- Enables Advanced Tagged Templates which safely execute function logic (like sanitizing HTML or formatting currency) natively against the interpolated string.
What are Symbols and WeakMaps?
Symbol: Unique, immutable primitive (used for object property keys).
WeakMap: Map with weak references to keys (garbage-collectable).
What problems does this solve?
- Symbols provide 100% guaranteed unique hash keys, ensuring third-party library properties never accidentally overwrite existing internal object methods.
- WeakMaps securely link private metadata to DOM elements without causing terminal memory leaks when the DOM elements are destroyed.
- Allows strict encapsulation of deeply private object configurations that absolutely cannot be extracted via `Object.keys()`.
What are Generators and Iterators?
Iterator: Object with a next() method returning { value, done }.
Generator: Function that can pause/resume execution using yield.
What problems does this solve?
- Allows developers to forcefully pause an executing function indefinitely and manually resume its logic precisely where it was halted.
- Generates functionally infinite data lazily (like massive prime number lists) without blowing out memory stacks by computing the entire list upfront.
- Provides the low-level mechanical foundation enabling async/await syntaxes and custom iterable custom object sequences.