JavaScript is the foundation of modern web development. Whether you're a junior or senior developer, you need to understand the core mechanics of the language.
A closure is a function bundled together with references to its surrounding state (lexical environment). In practical terms, it means inner functions "remember" variables from their outer function even after the outer function has returned. Closures are the foundation of patterns like data privacy, currying, and memoization.
The Event Loop is JavaScript's concurrency model. Since JS is single-threaded, the event loop continuously monitors the Call Stack and Task Queues. When the stack is empty, it pushes the next task. Key insight: Microtasks (Promises) are processed before Macrotasks (setTimeout, setInterval). Understanding this order is crucial for debugging async code.
== performs type coercion before comparison (e.g., 0 == '0' is true). === is strict equality—it compares both value and type without coercion. Best practice: always use === to avoid unexpected type conversion bugs.
Every JavaScript object has a hidden [[Prototype]] link to another object. When you access a property, JS walks up the prototype chain until it finds it or hits null. This is how methods on Array.prototype or Object.prototype are shared. ES6 class syntax is just syntactic sugar over this mechanism.
var is function-scoped and hoisted (initialized as undefined). let and const are block-scoped and have a "Temporal Dead Zone" (TDZ) where they exist but can't be accessed before declaration. const prevents reassignment but doesn't make objects immutable.
Hoisting is JavaScript's behavior of moving declarations to the top of their scope during compilation. Function declarations are fully hoisted (you can call them before they appear). var declarations are hoisted but not initialized. let/const are hoisted but remain in the TDZ.
The value of this depends on how the function is called:
window (browser) or global (Node)new): The newly created instancethis)call/apply/bind: Explicitly setPromises handle async operations and avoid callback hell. Async/Await is syntactic sugar over Promises that makes async code look synchronous. It allows try/catch for error handling and improves readability. Under the hood, await pauses execution until the Promise resolves.
Map: Keys can be any type; strongly referenced (prevents garbage collection); iterable. WeakMap: Keys must be objects; weakly referenced (allows GC if no other references); not iterable. Use WeakMap for caching data tied to DOM elements or objects that may be deleted.
Debounce: Delays execution until the user stops triggering the event (e.g., wait 300ms after last keystroke before searching). Throttle: Ensures the function runs at most once per time period (e.g., max once per 100ms during scroll). Both are performance optimizations for high-frequency events.
Bubbling (default): Event fires on the target, then bubbles up to ancestors.
Capturing: Event fires on ancestors first, then propagates down to target.
Use event.stopPropagation() to stop bubbling. addEventListener(..., true) enables capture phase.
Currying transforms a function with multiple arguments into a sequence of functions, each taking one argument: f(a, b, c) becomes f(a)(b)(c). It enables partial application—creating specialized functions from general ones. Common in functional programming.
undefined: Variable declared but not assigned; function returns nothing; missing object property.
null: Explicitly assigned to represent "no value."
Note: typeof null returns "object" (a famous JS bug), while typeof undefined returns "undefined".
Generators (function*) can pause execution with yield and resume later. They produce an iterator that returns values on demand. Use cases: lazy evaluation, infinite sequences, and managing async flow (used by libraries like redux-saga).
ES6 Modules (import/export): Static analysis at compile time; enables tree-shaking; works in browsers.
CommonJS (require/module.exports): Dynamic loading at runtime; no tree-shaking; Node.js legacy format.
Modern projects should use ES6 modules for better optimization.