165 JavaScript interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
JavaScript is a programming language that runs in browsers and on servers, handling application logic and interaction with the DOM. The questions cover types and variables, hoisting and closures, this binding, prototypes, Promises and async code, modern syntax such as destructuring, browser APIs, the event loop, and coding challenges like writing a debounce.
and 60 more topics.
var, let, and const all declare variables in JavaScript, but they differ in scope, re-declaration rules, and re-assignment behavior. - var has function scope — the variable "leaks" out of any block it's declared in, as long as it's inside a function. let and const…
JavaScript has 7 primitive types: string, number, boolean, null, undefined, symbol, bigint. What they share: they are immutable and copied by value. Not primitives: object, array, function, Date, Map, Set — all objects, all copied by reference. The usual follow-up: "if primitives have no methods,…
Symbol is a primitive type that produces a unique value. Every Symbol() call returns a value that equals no other, even when the description is the same. Main uses: - Avoiding property-name collisions: used as object property keys so another library cannot overwrite them. -…
== coerces both sides to the same type before comparing; === does not coerce, so different types are false right away. == (loose equality) === (strict equality) --------- Type coercion Yes No 0 and '0' true false null and undefined true false NaN and NaN…
Type coercion is JavaScript converting types automatically when an operator receives mismatched types. Two rules cover nearly every case: 1. + prefers strings — one string operand turns it into concatenation. 2. Every other arithmetic operator coerces to number. For objects, JS needs a primitive…
Falsy values are those treated as false in a boolean context. There are exactly 8, worth memorizing: Everything else is truthy — including things that look "empty": The pitfall that actually bites — 0 and '' are valid values: For the same reason, for defaults…
NaN (Not a Number) is the result of a failed numeric operation: Under IEEE 754, NaN equals nothing — not even itself. That is a floating-point standard rule, not a JavaScript quirk. Checking it correctly: Note: typeof NaN returns 'number'. NaN is still of type…
Hoisting is the JavaScript engine registering every declaration in a scope before running the first line of that scope. So a name can "exist" before its declaration line, but whether you can use it yet depends on the kind of declaration. Declaration Reading it before…
The TDZ is the span from the start of a block to the declaration line of a let/const binding. Inside it the variable exists but is uninitialized, and touching it throws ReferenceError. That typeof x line is the favorite follow-up: typeof is normally safe on…
The scope chain is JavaScript's mechanism for looking up variables from the current scope outward to the global scope. When a variable is not found in the current scope, JS looks in the parent scope, continuing upward to global. If not found at global, a…
A closure is when a function remembers variables from the outer scope where it was declared, even after the outer function has returned. It keeps a reference to the variable itself, not a copy of its value. makeCounter has returned, yet next can still read…
When using var in a for loop, all callbacks share one variable i: var is function-scoped, so the whole loop has a single i. Why it prints 3 3 3: setTimeout only queues the callback, and it runs after the for loop has finished. By…
Function declarations are fully hoisted (both name and body), so they can be called before they are declared. Function expressions only hoist the variable declaration (undefined with var), and cannot be called before assignment.
Three ways to define a function, differing in hoisting, this, and what the function comes with. declaration expression arrow ------------ Body hoisted yes no no Own this yes yes no (inherits lexically) arguments yes yes no Usable with new yes yes no As an object…
A callback is a function passed into another function to be called later. JavaScript runs on one thread. Waiting on the network or disk in a blocking way freezes the UI. Callbacks let you register "do this when the result arrives" and hand the thread…
A higher-order function (HOF) is a function that takes a function as an argument, returns a function, or both. Reading the example: filter takes a predicate, so you change the filtering rule without rewriting the loop. withPrefix('ERROR') returns a new function that already remembers the…
An IIFE is a function defined and invoked immediately. The wrapping parentheses are required: they turn a function declaration into a function expression so it can be called on the spot. Before ES6 JavaScript had only function scope, so an IIFE was the only way…
A pure function satisfies two conditions: 1. The same input always produces the same output. 2. No side effects — it changes nothing outside its own scope. Why it matters: - Tests need no mocks — call it, compare the result, done. - Cacheable (memoization),…
...args collects the remaining arguments into a real Array. Compared with arguments: ...rest arguments --------- Type a real Array array-like, needs Array.from() Contents only the unnamed arguments all arguments In arrow functions yes no Nameable yes no Do not confuse rest with spread — same…
Function composition chains small functions into a bigger one, where each output feeds the next input. They differ only in reading direction: Why it beats intermediate variables: Where it shows up in practice: Redux applyMiddleware, RxJS operator chains, PostCSS/Babel plugin pipelines. Note 1: every function…
Callback hell is asynchronous callbacks nested several levels deep, indenting the code into a pyramid and duplicating error handling at every level. Two real problems, not merely ugliness: error handling repeats at each level, and try/catch does not work. Rewritten with async/await: And parallelism when…
this depends not on where a function is defined but on how it is called. Four rules, highest precedence first: Arrow functions sit outside these four rules — they have no own this, taking it lexically from the enclosing scope, and call/bind cannot change it.…
In strict mode, this inside a regular function is undefined instead of the global object (window in browsers, globalThis in Node). So when a method is detached from its object and called as a plain function (no obj. in front), the bug shows up immediately:…
All three set this explicitly; they differ in how arguments are passed and when the call happens. Calls now Arguments Returns ------------ call yes one by one the function's result apply yes an array the function's result bind no one by one (partial allowed) a…
Arrow functions have no this of their own; they take this from the scope around where they are written. The curly braces of an object literal do not create a scope for this, so the scope around greet is the one outside obj (a module…
Calling new Foo() makes JavaScript do four things in order: Reimplementing new makes it concrete: The step-4 rule is a favorite follow-up: returning a primitive is ignored; only returning an object (a function included) overrides this. Note: what happens when you forget new on a…
In a class, this is the instance calling the method: call counter.increment() and this is counter. For a regular method, this is decided at call time, so pulling the method off the object loses this. After destructuring, increment() is called without counter. in front, so…
The prototype chain is the path JavaScript follows to find a property. Every object has a hidden link to its prototype. If obj.name is not on obj, JS checks the prototype, then the prototype's prototype... until it reaches null, where it stops and returns undefined.…
prototype is a property of a constructor function holding what its created objects share; proto is each object's link pointing to that place. prototype proto --------- Lives on Functions (constructors) and classes Every object What it is An object holding methods shared by the instances…
Object.create(proto) creates a new object whose prototype is proto. The child has no greet property of its own; when you read child.greet, JS does not find it on child and keeps looking up the prototype chain into proto. The second argument is an object of…
obj instanceof Foo checks whether Foo.prototype exists in obj's prototype chain. How it works: instanceof starts at the prototype of obj and walks up the chain, comparing each link with Foo.prototype. A match gives true; reaching the end gives false. Because it only compares prototypes,…
Destructuring unpacks values from arrays/objects into separate variables in one statement. It supports default values, renaming (aliases) and nested destructuring. Reading the object line piece by piece: - Alias: name: fullName reads user.name but assigns it to fullName. No name variable is created. - Default:…
Same ... syntax, opposite direction: spread "opens" an array or object into separate elements, while rest "collects" several elements into one array or object. Spread Rest --------- What it does Expands Collects Appears in Function calls, inside [...], inside {...} Function parameters, left side of…
Template literals are strings written with backticks instead of quotes. They give you three features: - Interpolation: embed any JS expression with the ${...} syntax. - Multi-line strings: a real line break in the source becomes a line break in the string, no newline escape…
Classes are a clearer OOP syntax for creating objects. Differences from function constructors: classes cannot be called without new (throws TypeError), methods are non-enumerable (do not appear in for...in), and classes are hoisted but sit in the TDZ like let/const: using one before its declaration…
Private fields use a prefix and are only accessible inside the class body. This is real privacy at the engine level, unlike the name convention: Testing whether an object carries the field — the in syntax for private names (ES2022): Note about the error type:…
for...in iterates keys, for...of iterates values. for...in for...of --------- Iterates enumerable keys values of an iterable Walks the prototype chain yes no Works with plain objects Array, String, Map, Set, NodeList, generators Plain objects yes TypeError — not iterable Two reasons not to use for...in…
They differ in what a key may be and how they relate to garbage collection. Map WeakMap --------- Keys any type objects / symbols only Iterable yes no size yes no Keeps keys alive yes no (weak references) What "weak" buys you: once the key…
Set is a collection of unique values; WeakSet is the object-only variant that holds weak references. Set compares with SameValueZero, so NaN behaves differently from ===: WeakSet offers only add/has/delete — no size, no iteration: How to choose: need counting, iteration, or primitive values →…
ES modules are JavaScript's standard module system, working in both browsers and Node. Four properties to remember: 1. Statically analysable — import/export are resolved at parse time, not at runtime. That is what makes tree-shaking possible. 2. File-scoped and always in strict mode. 3. Evaluated…
A Proxy wraps an object and intercepts operations on it (reads, writes, in, delete...). Each operation maps to a function in the handler called a trap: get, set, has, deleteProperty... Reflect is an object with functions named after each trap that perform that operation's default…
Both perform shallow copies. Object.assign() copies into an existing target, so if the target has a setter, that setter is called. Spread creates a new plain object and defines properties directly on it, calling no setters. Both copy own enumerable properties, including Symbol keys. For…
The string methods added from ES6 onward, which replace most simple regex work: Two common follow-ups: 1. includes is case-sensitive — normalize yourself for a case-insensitive check: 2. replaceAll is safe with strings but requires the g flag with a regex: Unicode caveat: these methods…
at(index) reads an element and understands negative indices. Compared with the older forms: Why arr[-1] does not work: array indices in JavaScript are really string keys on an object. arr[-1] looks up the key '-1', an ordinary property that does not exist, so it returns…
A Promise represents the future result of an async task, such as an API call. It has 3 states: - pending: waiting - fulfilled: success (resolve) - rejected: failure (reject) Once fulfilled or rejected, it never returns to pending. Promises reduce callback hell and make…
- .then(...): runs when the Promise succeeds. - .catch(...): runs when an error happens in the previous Promise chain. - .finally(...): always runs at the end, success or error. Example: Beginner tip: use finally for UI cleanup, such as turning off loading state.
Both are asynchronous work queues, but microtasks have absolute priority. Microtask Macrotask --------- Sources .then/.catch/.finally, await, queueMicrotask, MutationObserver setTimeout, setInterval, I/O events, DOM events When it runs the entire queue drains after each macrotask one per loop turn The browser's actual loop: The commonly wrong…
async/await is syntax for writing Promise-based asynchronous code that reads top to bottom like synchronous code. A function declared async always returns a Promise; await pauses that function until the Promise after it settles, then hands back its value. Both functions fetch a user and…
Put await inside a try/catch block. When a promise rejects, await throws that error like a normal exception, so catch can handle it. A common follow-up: inside try you must write return await res.json(), not return res.json(). Without await, the function hands the pending promise…
No. setTimeout(fn, 0) queues the callback as a macrotask, so it runs only after the call stack empties and every microtask has been processed. The HTML spec also mandates a 4ms minimum once timers nest five levels deep: Background tabs are throttled far harder (often…
A race condition occurs when several asynchronous operations overlap and the outcome depends on which finishes first — an order nothing guarantees. The classic case: a search box where a stale response arrives after a newer one and overwrites the correct result. Three remedies, in…
An unhandled rejection is a rejected Promise with no handler attached — no .catch(), no try/catch around an await. The consequences differ by environment: Default behavior ------ Node 15+ terminates the process (changeable with --unhandled-rejections=warn) Browser logs a console warning, the app keeps running Install…
The DOM (Document Object Model) is the tree of objects the browser builds after parsing HTML. Each tag becomes an element node, the text inside becomes a text node, and document is the root. JavaScript does not edit the HTML file; it reads and changes…
They differ in how they select, what they return, and whether the result tracks the DOM. Returns Live / static forEach works ------------ getElementById Element or null — — querySelector Element or null — — querySelectorAll NodeList static yes getElementsBy HTMLCollection live no (Array.from first)…
Event delegation attaches one listener on a parent instead of one per child, then relies on event bubbling to identify what was clicked. Three benefits: 1. Less memory — one listener instead of thousands. 2. Works with content added later — new rows need no…
Two entirely different jobs: one blocks the browser's default behavior, the other blocks the event's travel. preventDefault() stopPropagation() --------- Blocks the default action (submit, follow link, tick checkbox) bubbling / capturing Event keeps travelling yes no Detectable via e.defaultPrevented — There is also stopImmediatePropagation(), which…
fetch() is the Promise-based HTTP API that replaced XMLHttpRequest. The most surprising part — fetch does not reject on server errors: That is why every production fetch wrapper starts with if (!res.ok) throw .... fetch XMLHttpRequest --------- API Promise, async/await callbacks / events HTTP errors…
A Web Worker runs JavaScript on its own thread, so heavy computation never freezes the interface. Workers cannot touch the DOM, window or document. They do have fetch, WebSocket, IndexedDB and crypto — enough for most data work. Data passed through postMessage is copied (structured…
IntersectionObserver reports asynchronously when an element intersects (or leaves) the viewport or a container. isIntersecting is true as soon as the element overlaps the observed area, even partially. threshold only decides when the callback fires. To know whether the element is at least 50% visible,…
MutationObserver watches for changes to the DOM tree: attributes changing, child nodes being added or removed, text content changing. The callback does not run the moment the DOM changes; it is queued as a microtask, so several changes made in the same synchronous block are…
Three client-side stores differing in who can read them, how long they last, and whether they travel to the server. Cookie localStorage sessionStorage ------------ Size ~4KB ~5-10MB ~5-10MB Sent with every request yes no no Readable from JS yes, unless HttpOnly yes yes Expiry configurable…
CustomEvent lets you create custom events with data attached in detail. Dispatch with element.dispatchEvent(event). Two options you will use: - bubbles: true: an event dispatched on a child element rises through its ancestors, so you can listen once on a container or document. The default…
requestAnimationFrame(cb) schedules a callback to run just before the browser's next paint. Three reasons it beats setTimeout(fn, 16): 1. Synchronised with the real refresh cycle — correct on 120Hz displays too, with no frame drift or stutter. 2. Pauses when the tab is hidden —…
All three read/write an element's content; they differ in whether they understand HTML and CSS: - innerHTML: reads/writes HTML markup. On write, the string is parsed into real DOM, so assigning user input here is an XSS hole. - textContent: reads/writes the text of all…
Debounce delays calling a function until calls have stopped for delay ms, so the API is not hit on every keystroke. Each call clears the old timer and sets a new one, so only the last call survives until delay runs out. timer lives in…
Throttle caps the call rate at one per limit ms — it fires immediately, then blocks further calls until the window ends. The first call runs right away and sets waiting; every call in the next 100ms is dropped, and the flag clears when the…
A deep clone copies every nested value recursively, so the copy shares no child object with the original: changing the copy does not affect the original. Why each line is written this way: - Check null first: typeof null is 'object', so checking only typeof…
Flattening turns a multi-level nested array into a single-level array, like Array.prototype.flat. The natural approach is recursion: when an item is an array, flatten it and spread it into the result; when it is a plain value, push it as is. When flatten hits a…
Promise.all takes an iterable of promises (or plain values) and returns one promise that resolves with an array of results in input order once all of them succeed, and rejects as soon as any one rejects. What the interviewer wants explained: - Promise.resolve(item): inputs can…
useLocalStorage is a custom hook that behaves like useState, but the value is saved to localStorage: it survives a page reload, and when another tab changes it, this tab updates too. What each part does: - Lazy initializer: passing a function to useState reads localStorage…
The idea: put an empty element (a sentinel) at the end of the list and watch it with IntersectionObserver. This browser API tells you when an element enters the viewport, so you don't need a scroll listener and manual position math. When the sentinel shows…
A mini Redux built from Context + useReducer has three parts: a reducer that takes the old state and an action and returns the new state, a Provider that holds the state at the root of the component tree, and hooks that let child components…
Exponential backoff means retrying a failed operation and waiting twice as long before each new attempt (1s, 2s, 4s…). The point is to give the other service time to recover instead of piling requests onto it while it is overloaded. The function calls fn and…
Deep equality compares every nested value recursively. === does not work for objects because it compares references: two different objects with the same content are still false. What each branch does: 1. a === b: equal primitives, or the same object, are done immediately. This…
Memoize caches a function's result per argument, so a later call with the same arguments returns the stored result instead of recomputing. Use it only for pure functions: the same input always gives the same output with no side effects. A key built with JSON.stringify(args)…
FizzBuzz iterates from 1 to n — print 'Fizz' if divisible by 3, 'Buzz' if divisible by 5, 'FizzBuzz' if divisible by both, otherwise print the number. The basic version must check 15 first, because checking 3 first would stop 15 at 'Fizz'. The concatenation…
An LRU (Least Recently Used) cache evicts the least recently accessed item when it reaches capacity. In JavaScript, Map preserves insertion order so it can stand in for a Doubly Linked List for a simpler implementation. Why the classic design is HashMap + Doubly Linked…
The three methods differ first in purpose and return value: - forEach: iterates for side effects (logging, API calls, writing to an outer variable). Returns undefined, creates no new array. - map: transforms each element and returns a new array of the same length. It…
Two static methods that group an iterable's elements by the value a callback returns, replacing hand-written nested reduce. - Object.groupBy(items, fn) → an object with no prototype (null-prototype); keys are strings/symbols (callback value is coerced to string). - Map.groupBy(items, fn) → a Map; keys keep…
Promise.withResolvers() returns an object with promise, resolve, and reject together, exposing the two control functions outside the executor. The pain with new Promise(executor): to resolve a promise from elsewhere (an event handler, a library callback, a message queue) you declare empty variables and assign resolve…
Array.fromAsync() builds an array from an async iterable (or a sync iterable of promises) and returns a Promise. - Iterates sequentially: it finishes awaiting one element before taking the next, and mapFn (if given) is awaited each time too. Good for streamed/paginated sources processed one…
ES2025 adds set algebra directly on Set, replacing manual array conversions. - Return a new Set: union, intersection, difference, symmetricDifference. - Return a boolean: isSubsetOf, isSupersetOf, isDisjointFrom. Key gotcha: the argument needn't be a real Set — it must be a Set-like object (with size,…
structuredClone(value) is a built-in deep-clone using the platform's structured clone algorithm (the same mechanism behind Web Worker postMessage). Better than JSON.parse(JSON.stringify(x)) because it: - Preserves Date, RegExp, Map, Set, ArrayBuffer, TypedArray, Blob, File — JSON mangles these (Date → string, Map → {}). - Handles…
Three methods for cleaner access from the end of an array. - at(index) supports negative indices: at(-1) is the last element. The old arr[arr.length - 1] is verbose, and awkward when arr is an expression. - findLast(fn) / findLastIndex(fn) scan right-to-left, returning the last matching…
In a CommonJS file (.js when package.json has no "type": "module"), the order is: sync → nextTick → promise → then timeout and immediate in a non-deterministic order. Why: 1. console.log('sync') runs synchronously first. 2. Once the synchronous stack drains, Node processes the nextTick queue…
Because the two live in different event loop phases, and where you call them decides which phase comes first. One loop iteration walks the phases in order: timers → pending callbacks → poll → check → close callbacks. setTimeout fires in timers, setImmediate in check.…
In expression position (assigned to a variable, passed as an argument) both produce '[object Object]'. Only when {} + [] sits at the start of a statement does it yield 0, e.g. eval('{} + []') or typing it into the Chrome DevTools console. The Node…
JavaScript numbers are IEEE-754 doubles (64-bit binary). Fractions like 0.1 and 0.2 have no exact binary representation, so they are rounded and the sum comes out as 0.30000000000000004. For money, do not use floats. Three common approaches: - Store integers in the smallest unit: VND…
Plain-object keys are always coerced to strings (or Symbols). Every object used as a key becomes '[object Object]', so distinct entries overwrite each other. Use Map when: - Keys are not strings (objects, numbers, functions) — Map matches keys by reference/original value, with no coercion.…
delete removes the property entirely; assigning undefined keeps the property and only changes its value. The difference shows up in any enumeration or existence check. Two common follow-ups: - delete returns true even when the property does not exist; it returns false only for non-configurable…
No. Object.freeze is shallow: it blocks adding/deleting/modifying properties at the top level only, but nested objects stay mutable because freezing locks the reference, not what the reference points to. Deep freeze requires recursion: Call Object.freeze(obj) before recursing. With a circular reference (a points to b,…
Because this in JavaScript is decided at call time, not at definition time. Assigning a method to a variable copies only the function reference; the receiver (obj.) does not travel with it. A bare fn() call leaves this as undefined in strict mode/modules (or globalThis…
The bug appears when a legitimate value is falsy. falls through on every falsy value: 0, '', false, NaN, null, undefined. ?? falls through only on null or undefined. Real cases that get hit: boolean feature flags (false read as "unset"), quantities or prices of…
A destructuring default fires only when the value is undefined, never for null. null is a valid value, so it is assigned as-is. Handling null from an API: destructure first and normalize separately, or use ?? on the extracted value. Renaming uses the { key:…
With var it prints 3 3 3. With let it prints 0 1 2. var is function-scoped, so all three callbacks close over the same i. By the time the timers run (after the loop finishes), i is 3. let is block-scoped, and the spec…
They are hoisted — the binding is created at the top of the block — but left uninitialized. The span from the start of the block to the declaration is the TDZ (Temporal Dead Zone); touching the variable there throws a ReferenceError. The distinction matters:…
Both are shallow: they copy only own enumerable properties at the first level. Nested objects stay shared by reference. This is a classic React/Redux bug: you think you produced new state, but the nested object is the old one, so a reference check sees no…
Output: 1, 4, 3, 2. - 1 and 4 are synchronous code and run to completion first. - 3 sits in the microtask queue (a promise callback). Microtasks are drained as soon as the call stack empties, before the event loop picks up a new…
The spec says an async function always wraps its result in a Promise. return 1 produces a Promise fulfilled with 1; throw err produces a rejected Promise rather than throwing synchronously. Returning a Promise from inside does not create a double wrapper — the promise…
forEach ignores the callback's return value. An async callback returns a Promise, forEach discards it and moves to the next element — so the loop finishes immediately while the save() calls are still in flight. Two fixes, pick per requirement: Two more problems with the…
Because by the time the callback runs, the try block is long gone. try/catch only guards what executes on its own synchronous call stack. setTimeout merely registers the callback and returns; try exits and the stack unwinds. Later the event loop runs the callback on…
For a dashboard the answer is almost always Promise.allSettled: each widget renders independently, so one failing API should not blank the whole page. Pick by semantics: - all — fail-fast; rejects as soon as one input rejects. Use it when a missing piece makes the…
Rule of thumb: parallel by default, sequential only when constrained. Sequential is mandatory when: - A request depends on the previous result (fetch a token, then call the API; use nextCursor to paginate). - Writes must be ordered (charge the card, then create the order).…
Use AbortController — the only way to cancel an in-flight fetch. The short form is AbortSignal.timeout(): When you also need manual cancellation (user navigates away, types a new query), manage the controller yourself: For both timeout and manual abort, combine signals with AbortSignal.any([controller.signal, AbortSignal.timeout(5000)]). Common…
Backoff means each retry waits exponentially longer, plus random jitter so many clients do not all retry at the same instant. Retry only when it is safe: - Network errors, timeouts, 429, 503, 502 — transient. - Never retry 400, 401, 403, 422 — they…
This is a stale response problem — several requests are in flight and responses are not guaranteed to arrive in send order. The request for "ipho" can land after the one for "iphone" and overwrite state. Three approaches, best first: 1. Cancel the previous request…
A standard debounce only delays when the call happens; it knows nothing about Promises. Three issues appear when the inner function is async: 1. The return value is lost. debounce(fn) returns undefined, so await debouncedSearch(term) is meaningless. To make it awaitable the wrapper must hold…
The final value is identical — both give the caller the same result. The difference shows up in try/catch and in stack traces. With return promise the function leaves the try block immediately and hands the promise to the caller; by the time it rejects,…
The browser runs a fixed 5-step pipeline: 1. Parse HTML → DOM: HTML bytes become a node tree. 2. Parse CSS → CSSOM: every stylesheet is fetched and parsed into a style tree. 3. Render tree: DOM + CSSOM are combined, dropping non-rendered nodes (display:…
They differ in size, lifetime, and whether they are sent to the server automatically. - Cookie — ~4KB each, automatically attached to requests sent to its domain and path (including images and API calls). It is scoped by domain, not origin, and cross-site requests still…
An event travels through 3 phases: capturing (from window down to the target), target (at the element itself), then bubbling (back up to window). By default addEventListener listens in the bubbling phase; pass { capture: true } to listen on the way down. Event delegation…
Each attribute blocks a different class of attack: - HttpOnly — JS (document.cookie) cannot read the cookie. This is the main defence when the page has an XSS hole: injected script still cannot steal the session. - Secure — the cookie is only sent over…
A service worker goes through register → install → (waiting) → activate → idle/terminated. - install: runs once per script version, typically to precache assets. - waiting: if an existing service worker still controls the page, the new one waits — exactly why users keep…
Three steps: preview immediately, compress before sending, release resources. Preview with URL.createObjectURL(file) — faster than FileReader.readAsDataURL because it does not base64-encode the whole file into a string. Always revokeObjectURL when the image is removed or the component unmounts, otherwise the blob stays in memory. Compress…
Cause: the browser paints with the default theme first, and only after the app's JavaScript runs (reading localStorage, setting state) does it switch to dark. That gap is the white flash. The fix is to decide the theme before the first paint, with a tiny…
Use Intl rather than hand-rolled thousand-separator and date-concatenation helpers. Common follow-ups: - VND has no minor unit — Intl knows that, while hand-written helpers usually print a stray ".00". - Vietnamese number formatting is the inverse of English: dot groups thousands, comma marks decimals. Swapping…
Two jobs: tell the user and recover automatically when the network returns. Detection. navigator.onLine plus the online / offline events tell you whether the machine has a connection: Know the limitation: onLine === true only means the device is attached to a network, not that…
Three common ways: setInterval then clearInterval at 10, recursive setTimeout, or async/await with a sleep helper. The exercise checks whether you understand that timers do not block the thread and whether you remember to stop them. A common mistake is for (var i = 1;…