skip to content

JavaScript

4 roadmaps501 questionsupdated

JavaScript is the language of the browser and, via Node, a large share of backend work too. Interviews lean on its distinctive runtime semantics — dynamic types and coercion, closures, prototypes, the single-threaded event loop, and module execution — because those are where day-to-day bugs actually come from.

on this pageshow

guide

overview

~2 min

JavaScript interviews test whether you understand the runtime underneath the syntax. Rounds usually open on scope: which binding a name resolves to, why a declaration can be visible above its own line, and what a closure keeps alive after its function returns. From there the conversation moves to the object model, where `class` is a thin layer over objects delegating to other objects, and to the scheduler, where a short snippet and the question "what order does this log in?" separates people who have debugged asynchronous code from people who have only written it. Coercion questions check whether you can predict a conversion from the rules rather than recite a list of surprises. Practical rounds test fluency with collections, errors and the everyday built-ins, and senior rounds drift toward modules: how a module graph is loaded, what a bundler can safely remove, and what breaks when ES modules and CommonJS meet. The hub follows those seams. The language core is [Types and Coercion](/topics/lang-javascript-types-coercion), [Scope and Closures](/topics/lang-javascript-scope-closures) and [Prototypes and Inheritance](/topics/lang-javascript-prototypes). Everyday code lives in [Functions, Iterables and Collections](/topics/lang-javascript-functions-collections) and [Errors and Built-in Objects](/topics/lang-javascript-errors-builtins). Asynchrony is split in two: [Event Loop and Concurrency](/topics/lang-javascript-event-loop) is the scheduler, and [Promises and Async/Await](/topics/lang-javascript-promises-async) is the API you program it with. [Modules and Bundling](/topics/lang-javascript-modules) covers how separate files become one program, and [DOM and Browser APIs](/topics/lang-javascript-dom-browser) is the narrow edge where the language meets the page. Learn it roughly in that order. Types and scope come first, because nearly every later answer assumes you can say what a value is and which variable a name points at. Functions and collections next, since they are most of the code you write in a live exercise, then prototypes, which explain what a method call does and what `class` actually builds. Take the event loop before promises: the promise questions that feel tricky are usually scheduling questions in disguise. Modules and the DOM weigh most when the role names them: front-end work leans on the browser and bundling, Node work on module loading and interop.

primer

### A value has a type; a variable does not Any binding can hold any primitive or object, and the engine converts between kinds whenever an operator needs a different one — not at random, but by a fixed algorithm for each kind it asks for. An interviewer who shows `[] + {}` is checking whether you can run that algorithm in your head, and whether you know when strict comparison or an explicit conversion is the better tool. Numbers add a second layer: an ordinary number is a binary double, with the precision and integer-range limits that implies. ### Names resolve by where code is written; `this` by how it is called Scope is lexical: the nesting of functions and blocks in the source decides which binding a name refers to, and a scope's bindings are created when it is entered, before any of its lines run. That one fact explains hoisting and the temporal dead zone. `this` follows a different rule: a normal function gets it at each call, from how the call is made. An arrow function has none of its own and looks outward for it like any other name. ### A closure keeps variables, not snapshots A function holds a reference to the scope it was created in, so it can read and change those variables long after the outer call has returned. Because it keeps the variable itself, two closures made in the same scope share state, and callbacks created in a loop that reuses one binding all see its latest value. Private state, memoization and partial application all rest on this. ### Objects delegate to other objects Every object has a link to a prototype, and a property lookup that misses on the object continues along that chain. Methods live once on a shared prototype; `new` and `class` are ways of creating objects wired to the right one. Reads and writes are not symmetric, since lookup follows the chain and assignment normally does not. Descriptors, getters and setters, and `Proxy` are the tools for changing what a property access does. ### One thread, one stack, and queues Within a page, a worker or a Node process, your code runs one callback at a time, each to completion, on a single call stack. Everything asynchronous — timers, I/O, user events, promise reactions — is a callback waiting in a queue until the stack is empty. There are two tiers: tasks, taken one per turn of the loop, and microtasks, emptied completely after each task. Ordering puzzles, a frozen page and a late timer are all consequences of that design. ### A promise is a value for a result that is not ready yet Promises turn callbacks into values you can return, chain and combine, and `async`/`await` is syntax for writing that chain as straight-line code. The interview weight is on failure and timing: each step of a chain yields a fresh promise, a rejection travels down the chain until something handles it, and a forgotten `return` or `await` quietly detaches work from the code that should wait for it. ### Modules are linked before they run ES modules declare imports and exports statically, so the whole graph can be found, loaded and wired together before any module body executes. That static shape lets bundlers drop unused exports, and it is why an import stays connected to the exporting module's variable instead of freezing its value. CommonJS works the other way: `require` is an ordinary function call that executes a file and returns an object. Most interop and circular-dependency questions come from the collision of those two models. ### The language is not the platform ECMAScript defines the syntax and the built-ins: objects, arrays, promises, `JSON`, `Date`, regular expressions. The DOM, timers, `fetch` and Node's file system come from the host. Knowing which layer owns an API tells you where it exists and why code that works in one environment crashes in another. The built-ins have sharp edges worth knowing by name: lossy JSON, stateful regexes, months counted from zero.

Primitive
A value that is not an object: string, number, bigint, boolean, symbol, null or undefined. Primitives are immutable; calling a method on one uses a temporary wrapper object.
Type coercion
The engine's implicit conversion of a value to another type when an operator or context needs one, following fixed abstract operations such as ToPrimitive, ToNumber and ToString.
Truthy and falsy
Whether a value converts to true or false in a boolean context; a short fixed list of values is falsy, and everything else, empty arrays and objects included, is truthy.
Hoisting
The effect of creating a scope's bindings when the scope is entered, so declarations are known before their line runs; how usable they are before then depends on the declaration kind.
Temporal dead zone
The stretch between entering a scope and reaching a let, const or class declaration, during which the binding exists but any access to it throws a ReferenceError.
Closure
A function together with the scope it was created in, which keeps that scope's variables alive and shared for as long as the function itself is reachable.
this binding
The receiver a normal function sees, decided at each call by how it is invoked: as a method, with new, through call, apply or bind, or as a plain call.
Arrow function
A compact function form with no this, arguments or prototype of its own; it reads this from the enclosing scope and cannot be used as a constructor.
Prototype chain
The linked sequence of objects a property lookup walks when the property is not found on the object itself, ending at null.
Property descriptor
The record behind a property: its value or its getter and setter, plus the writable, enumerable and configurable flags that control how it can be changed and seen.
Proxy
A wrapper object whose handler traps intercept fundamental operations such as property reads, writes and deletes; Reflect supplies the default behaviour a trap can forward to.
Microtask
A job queued by a promise reaction, an await resumption or queueMicrotask; the whole queue is emptied after the current task, the macrotask, and before the next one starts.
Promise
An object standing for the eventual result of an asynchronous operation; it settles once, either fulfilled with a value or rejected with a reason.
ES module
A file loaded through import and export declarations; it runs in strict mode, has its own top-level scope, and is linked with its dependencies before it executes.
Live binding
An ES module import that shows the exporter's variable as it currently is, read-only on the importing side, rather than a copy taken at import time.
CommonJS
Node's original module format, in which require synchronously runs a file and returns its module.exports object; still common in published packages.
Tree shaking
A bundler's removal of code nothing imports, which depends on static import structure and on modules not doing needed work as a side effect of loading.
Iterable
Any object with a Symbol.iterator method that returns an iterator; the protocol behind for...of, spread, array destructuring and Array.from.
Generator
A function declared with function* that returns an iterator and pauses at each yield, resuming when the consumer asks for the next value.
Event delegation
Handling events for many child elements with one listener on a shared ancestor, relying on event bubbling and on the event's target to identify the source.

The sections stack. Types and scope define what a value is and which variable a name points at. Functions and collections sit directly on them: every array method takes a callback, and every callback is a closure over the code that wrote it. Prototypes supply the other half of a method call — where the method is found — while [The this Binding](/topics/lang-javascript-scope-closures-this-binding) decides which object it runs against. [The Prototype Chain](/topics/lang-javascript-prototypes-chain) and `this` are the two lookups inside every `obj.method()`, which is why interviewers often ask about them back to back. Asynchrony reuses all of it. A promise callback is a closure; `await` suspends a function and later resumes it with its scope intact; the order in which things resume is set by the [Microtask Queue](/topics/lang-javascript-event-loop-microtasks) and the task queue behind it. That is why [Output Ordering Puzzles](/topics/lang-javascript-event-loop-ordering-puzzles) sit under the event loop rather than under promises: the syntax is async, but the question is about the scheduler. Modules and the host form the outer ring. [ES Module Semantics](/topics/lang-javascript-modules-esm-semantics) decide when each file's top-level code runs and what its imports see; the [Browser vs Node Global Environment](/topics/lang-javascript-dom-browser-runtime-environments) decides which globals exist when it does. Errors cut across every layer: a rejected promise, a thrown `TypeError` and a failed `JSON.parse` are one error model reached from different places. A small example where several of these meet, run as an ES module so strict mode applies: ```javascript function makeCounter(label) { let count = 0; return { label, async tick() { count += 1; await null; return `${this.label}: ${count}`; }, }; } const counter = makeCounter('a'); const { tick } = counter; counter.tick().then(console.log); // "a: 2" tick().catch((err) => console.log(err.name)); // "TypeError" ``` Both calls share one `count`, because both closures hold the same binding, not a snapshot of it. Each async body executes without pausing until it reaches `await`, so both increments happen before either call resumes, and the first result reads 2. The destructured call has no receiver, so `this` is `undefined` in strict code; the `TypeError` that follows is not thrown at the call site but rejects that call's promise, and the handler receives it as a value.

  1. Types and Coercion →

    Primitives, equality and conversion rules are the vocabulary the other sections' answers are written in; learn to predict a conversion first.

  2. Scope and Closures →

    Hoisting, closures and this are where most rounds open, and where a wrong mental model shows up fastest.

  3. Functions, Iterables and Collections →

    Callbacks, array methods, Map and Set, and iterators are the material of nearly every live coding exercise.

  4. Prototypes and Inheritance →

    Explains what a method call and class syntax actually do; read it once closures and this feel routine.

  5. Event Loop and Concurrency →

    Learn the call stack and the two queues before promises, so ordering questions become mechanical rather than memorised.

  6. Promises and Async/Await →

    With the scheduler understood, chains, combinators and async/await become questions about error flow and concurrency.

  • Guessing the result of == from intuition: loose equality follows a conversion algorithm, and Equality and Conversion questions are built to punish guesses.

  • Assuming const makes data immutable: it fixes the binding only, so a const object or array can still be changed by any code holding a reference.

  • Expecting a method to remember its object: passed as a callback it loses its receiver, and written as an arrow function it never had one.

  • Using for...in over an array: it yields string keys and includes inherited enumerable properties; for...of or Object.keys usually says what you meant.

  • Treating setTimeout(fn, 0) as immediate: the callback waits for the running code and all pending microtasks, and a busy thread delays it further.

  • Awaiting inside a loop when the calls are independent: each iteration waits for the previous one, turning concurrent work into summed latency.

  • Starting a promise without returning or awaiting it: a surrounding try/catch cannot see its rejection, which surfaces later as unhandled.

  • Using a JSON.stringify and JSON.parse round trip as a deep copy: dates, undefined, functions, Map and cycles do not come back intact.

  • Reading window or document at a module's top level: the file crashes as soon as server-side code imports it, before any function is called.

This guide assumes an engine implementing ES2022 or later, which current evergreen browsers and maintained Node releases all do. Editions are named by year since ES2015, and interviewers still ask which release brought a feature, mostly to learn whether you can read older code: - **ES5 (2009)** — strict mode, `JSON`, property descriptors and the array iteration methods such as `map` and `filter`. - **ES2015** — the large release: `let` and `const`, arrow functions, classes, promises, modules, template literals, destructuring, `Map` and `Set`, symbols, iterators and generators, `Proxy` and `Reflect`. - **ES2017** — `async` and `await`. - **ES2018** — async iteration, and rest and spread for object properties. - **ES2020** — optional chaining, nullish coalescing, `BigInt`, `globalThis`, dynamic `import()` and `Promise.allSettled`. - **ES2021** — logical assignment operators and `Promise.any`. - **ES2022** — top-level `await`, class fields and `#private` members, `Object.hasOwn`, `Array.prototype.at` and the `cause` option on errors. - **ES2023** — array methods that return a copy instead of mutating, such as `toSorted` and `toReversed`, plus `findLast`. `structuredClone` is missing from that list on purpose: it comes from the web platform and is provided by browsers and by Node rather than by the language, a handy example of the language/host split.

JavaScript is standardised as ECMAScript by Ecma International's TC39 committee and implemented by engines such as V8, SpiderMonkey and JavaScriptCore. Interviewers expect you to place it in a few settings. In the **browser** it is the language with direct access to the DOM; WebAssembly complements it for compute-heavy code rather than replacing it. On the **server**, Node is the established runtime, with Deno and Bun as newer alternatives that also run TypeScript directly. There it competes with Python, Go and Java: the event loop suits I/O-heavy services better than CPU-bound work, and the draw is one language on client and server. **TypeScript** is the most common companion: a typed superset whose types are checked at build time and then erased, so every runtime question in this hub applies unchanged to TypeScript code. Bundlers and build tools such as webpack, Rollup, esbuild and Vite resolve modules, transpile newer syntax and drop unused code, which is why module semantics come up in front-end interviews. Frameworks such as React, Vue and Angular sit on top, and a framework question often turns out to be a closure, reference-equality or event-loop question underneath.

explore

report an issue with this guide →

questions

501 · 9 sections

Given `function makeCounter() { let n = 0; return () => ++n; }` and `const a = makeCounter(), b = makeCounter();`, what does `a(); a(); console.log(a(), b());` print, and why do the two counters not interfere?

level: juniorimportance: must knowfreq 70%
basics
~10 s

It prints 3 1. Every call to makeCounter creates a new environment with its own n, so the two returned functions close over two different bindings and count independently.

open as a page

In JavaScript, `for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); }` logs 3, 3, 3. Explain why, and give the smallest change that makes it log 0, 1, 2.

level: juniorimportance: must knowfreq 85%
basics
~20 s

var creates one function-scoped i shared by the whole loop, so all three deferred callbacks read the same binding, which already holds 3 by the time the timers fire. Declaring the counter with let gives each iteration its own i, logging 0, 1, 2.

open as a page

In JavaScript, why is a function's local variable not freed when that function returns, if an inner function it returned still refers to the variable?

level: juniorimportance: must knowfreq 58%
basics
~20 s

A function object stores a hidden pointer to the scope it was created in, so returning it keeps that scope reachable. Reachable memory is never collected, so the variable lives as long as the returned function does.

open as a page

In JavaScript, why does `function () { console.log('hi'); }();` throw a SyntaxError while `(function () { console.log('hi'); })();` runs, and what other forms make an immediately invoked function expression work?

level: juniorimportance: must knowfreq 62%
basics
~20 s

A statement that begins with the keyword function is parsed as a function declaration, which needs a name and cannot be invoked in place. Wrapping it in parentheses forces the parser to read it as an expression, and expressions are callable.

open as a page

In JavaScript, why can you call a function written as `function greet() {}` from a line above its definition, while calling a function stored by `var sayHi = function () {}` above that assignment throws a TypeError?

level: juniorimportance: must knowfreq 80%
basics
~20 s

A function declaration is created whole, name and body together, when the scope is entered, so it is callable anywhere in that scope. A function expression only becomes a function when its assignment line runs; until then the variable holds undefined.

open as a page

In JavaScript, how do `'toString' in obj` and `Object.hasOwn(obj, 'toString')` differ for a plain object literal, and when does that difference matter?

level: juniorimportance: must knowfreq 58%
basics
~20 s

The in operator searches the whole prototype chain, so it reports true for inherited names such as toString. Object.hasOwn checks only the object's own properties and reports false. Use hasOwn whenever you mean data the object itself carries.

open as a page

In a JavaScript class, what is the difference between `super(...)` and `super.someMethod()`, and where is each one allowed to appear?

level: juniorimportance: must knowfreq 72%
basics
~20 s

super(...) invokes the parent constructor and is legal only inside the constructor of a class written with extends. super.someMethod() calls the parent's version of a method with the current instance as this, and is legal in any method or accessor.

open as a page

In a JavaScript class body, what does declaring a field as #count = 0 give you that the older convention of naming it _count does not?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A #-prefixed field is privacy enforced by the engine: it can only be named inside the class body that declares it, it is invisible to Object.keys and JSON.stringify, and touching it elsewhere is an error. An underscore name is only a hint.

open as a page

In a JavaScript class, what does the `static` keyword do — which object does the member live on, and can you reach it from an instance?

level: juniorimportance: must knowfreq 72%
basics
~20 s

static installs a method or field on the class constructor itself instead of on instances. You call it as ClassName.member; reading it from an instance gives undefined, because the constructor is not on the instance's prototype chain.

open as a page

JavaScript engines run your code on a single call stack. What gets pushed onto and popped off that stack, and why does that mean two of your functions can never be executing at the same instant?

level: juniorimportance: must knowfreq 78%
basics
~20 s

The call stack holds one frame per function call that has started but not returned — its arguments, its locals, and the point to resume at. Calls push a frame, returns pop it, and because JavaScript has a single stack, only the top frame is ever running.

open as a page

In JavaScript, if a promise is already fulfilled at the moment you call .then(callback) on it, does callback run immediately? Explain when it actually runs and what schedules it.

level: juniorimportance: must knowfreq 66%
basics
~20 s

No. .then never calls back synchronously: it schedules a promise reaction job on the microtask queue. The callback runs after the currently executing script or task finishes, when the engine drains microtasks at its checkpoint.

open as a page

What does this script print, and why? console.log('start'); setTimeout(() => console.log('timeout'), 0); Promise.resolve().then(() => console.log('promise')); console.log('end');

level: juniorimportance: must knowfreq 85%
basics
~20 s

It prints start, end, promise, timeout. All the top-level synchronous code runs first, then the promise callback runs as a microtask once the script finishes, and the setTimeout callback runs last as a separate task.

open as a page

What does setInterval return, and what happens if the code that started a repeating timer is torn down without ever calling clearInterval with that value?

level: juniorimportance: must knowfreq 62%
basics
~20 s

setInterval returns a timer handle — a number in browsers, a Timeout object in Node — whose only use is to pass to clearInterval. Without that call the timer fires forever, keeping its callback and everything the callback closes over alive.

open as a page

Does setTimeout(fn, 100) guarantee that fn runs exactly 100 ms later? What does the delay argument actually promise?

level: juniorimportance: must knowfreq 78%
basics
~20 s

setTimeout's delay is a minimum wait, not an exact schedule. When it elapses the callback is only queued as a task; it runs after the currently executing code finishes and after any work already queued ahead of it, so it commonly fires late.

open as a page

In JavaScript, what does calling an `async` function return, and how do a plain `return 42`, a `throw`, and a `return somePromise` inside its body each show up in that returned value?

level: juniorimportance: must knowfreq 85%
basics
~20 s

An async function always returns a promise, never a raw value: return 42 fulfils that promise with 42, throw rejects it with the thrown error, and returning a promise makes the outer promise adopt that promise's eventual outcome.

open as a page

In a JavaScript async function, how does wrapping an `await` in try/catch let you handle a rejected promise, and what exactly does `await` do when the promise it is waiting on rejects?

level: juniorimportance: must knowfreq 78%
basics
~20 s

await rethrows a rejected promise's reason as an ordinary exception at the await point, so a normal try/catch around that await catches it. The catch parameter is bound to whatever value the promise rejected with, which need not be an Error.

open as a page

In JavaScript, a function loops over 10 user IDs and does `const user = await fetchUser(id)` inside the loop body, where each call takes about 200 ms. How long does the loop take overall, why, and how would you make the ten requests run concurrently?

level: juniorimportance: must knowfreq 80%
basics
~20 s

Awaiting inside the loop serializes the requests, so ten 200 ms calls take about 2 seconds. Start all ten promises first and await them together with Promise.all, and the whole batch takes roughly 200 ms.

open as a page

What is the difference between Promise.all and Promise.allSettled in JavaScript, and what does each of them fulfil with?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Promise.all rejects the moment any input promise rejects, and otherwise fulfils with an array of the values in input order. Promise.allSettled waits for every input and always fulfils, giving one {status, value or reason} object per entry.

open as a page

You run `await Promise.all(urls.map(url => fetch(url)))` over an array of 5,000 URLs. What actually happens, and why can Promise.all not limit how many requests are in flight?

level: juniorimportance: must knowfreq 62%
basics
~20 s

All 5,000 requests start immediately: map calls fetch for every URL before Promise.all ever runs. Promise.all only observes promises that are already in flight, so any concurrency cap must be applied where the work is started.

open as a page

In a CommonJS module, when you write `const cfg = require('./config')`, at what point does the code inside config.js actually run, and what value does require() hand back?

level: juniorimportance: must knowfreq 68%
basics
~10 s

require() runs the target module's body synchronously at the call site and hands back whatever value module.exports holds when that body finishes. The calling file is blocked until the required module completes.

open as a page

In JavaScript, what does the expression `import('./math.js')` evaluate to, and how does that differ from a static `import ... from './math.js'` declaration?

level: juniorimportance: must knowfreq 72%
basics
~20 s

import() is a syntactic form that starts loading a module at runtime and evaluates to a Promise for that module's namespace object. A static import declaration is resolved before any code in the file runs and binds the exported names directly.

open as a page

In ES modules, what is the difference between a named export and a default export, and how does the import syntax differ for each?

level: juniorimportance: must knowfreq 80%
basics
~20 s

A named export binds a value to a specific export name that importers must match exactly, using braces: import { parse } from './m.js'. A default export registers the value under the name "default", and the importer may bind it to any identifier it likes.

open as a page

In an ES module you write `var config = {}` and `function init() {}` at the top level. Are `globalThis.config` and `globalThis.init` defined afterwards, and how does that differ from the same two lines in a classic (non-module) script?

level: juniorimportance: must knowfreq 70%
basics
~10 s

No. Top-level declarations in an ES module live in that module's own scope, so globalThis.config and globalThis.init stay undefined. In a classic script the same declarations become properties of the global object.

open as a page

In an ES module `main.js` you write `console.log('main start');` and then, on the line below it, `import './dep.js';` — and `dep.js` logs `'dep evaluated'` at its top level. Which line prints first, and what rule decides that?

level: juniorimportance: must knowfreq 68%
basics
~20 s

The dependency prints first. Import declarations are hoisted and the whole module graph is linked before anything is evaluated, so dep.js runs to completion before any statement in main.js — including a statement written above the import.

open as a page

What is event delegation in the DOM, and why does a single delegated handler still work for list items that are added after the handler was attached?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Event delegation puts one listener on a container instead of one per child and identifies the child from the event object. Items added later are covered automatically, because the listener lives on the container, not on each child.

open as a page

A script whose first line is `const el = document.body` runs fine in a browser tab but throws `ReferenceError: document is not defined` under `node script.js`. Why is the DOM missing in Node, and what globals does Node supply instead?

level: juniorimportance: must knowfreq 78%
basics
~20 s

The DOM is not part of JavaScript. ECMAScript defines only the core language and built-ins such as Object, Array and Promise; document and window are supplied by the browser host. Node is a different host and supplies process, Buffer and its module globals instead.

open as a page

Why does calling .map() on the result of document.querySelectorAll() throw, and how do you get array methods over the elements it returns?

level: juniorimportance: must knowfreq 66%
basics
~20 s

document.querySelectorAll returns a NodeList, not an Array. It is array-like and iterable and does have forEach, but it does not inherit from Array.prototype, so map, filter and reduce are missing. Convert with Array.from(nodes) or [...nodes].

open as a page

What is the difference between setting an element's textContent and setting its innerHTML in the browser DOM, and when does that difference cause a bug?

level: juniorimportance: must knowfreq 78%
basics
~20 s

textContent treats the assigned string as literal text and shows it exactly as written; innerHTML runs it through the HTML parser and builds real nodes from it. Assigning untrusted data to innerHTML turns that data into page structure.

open as a page

A <ul> has a click handler that does `if (event.target.tagName === 'LI') { ... }`, but each <li> wraps its label in a <span>. Why does clicking the label do nothing, and how do you fix the dispatch?

level: middleimportance: must knowfreq 62%
basics
~20 s

event.target is the innermost element the click landed on — the span, not the li — so the tagName check fails. Match with event.target.closest('li') instead, and verify the result is inside your own container before acting on it.

open as a page

In JavaScript, what does the == (loose equality) operator do that === does not, and what do '5' == 5 and '5' === 5 each evaluate to?

level: juniorimportance: must knowfreq 86%
basics
~20 s

The == operator converts operands to a common type before comparing; === requires matching types and never converts. So '5' == 5 is true, because the string is converted to the number 5, while '5' === 5 is false.

open as a page

In JavaScript, what does the strict equality operator === compare, and how does it behave when its two operands have different types?

level: juniorimportance: must knowfreq 88%
basics
~20 s

=== returns true only when both operands have the same type and the same value. Different types are never converted, so the result is immediately false. Objects and arrays compare by reference, not by contents.

open as a page

In JavaScript, why does '5' + 3 give '53' while '5' - 3 gives 2? Explain what the + operator does with mixed operand types.

level: juniorimportance: must knowfreq 70%
basics
~20 s

Binary + is the only arithmetic operator that is also string concatenation: after converting both operands to primitives, if either one is a string it concatenates, otherwise it adds numerically. Every other arithmetic operator converts to number unconditionally, so '5' - 3 is 2.

open as a page

In JavaScript, which values are falsy — that is, which convert to false when used as an `if` condition — and which commonly-assumed-falsy values are actually truthy?

level: juniorimportance: must knowfreq 85%
basics
~20 s

JavaScript has a fixed falsy list: false, 0, -0, 0n, the empty string, null, undefined, and NaN. Every other value is truthy — including '0', 'false', the empty array, the empty object, and every function.

open as a page

In JavaScript, why does `0.1 + 0.2 === 0.3` evaluate to false, and what does `0.1 + 0.2` actually produce?

level: juniorimportance: must knowfreq 88%
basics
~10 s

JavaScript numbers are IEEE-754 binary doubles, and 0.1, 0.2 and 0.3 cannot be written exactly in binary. The stored approximations add up to 0.30000000000000004, a different double from 0.3, so === is false.

open as a page

In JavaScript, what is the difference between Array.prototype.slice() and Array.prototype.splice(), and what does each one return?

level: juniorimportance: must knowfreq 80%
basics
~20 s

slice() copies: it leaves the original array untouched and returns a new array holding the selected range. splice() edits in place: it removes and/or inserts elements in the original array and returns an array of the elements it removed.

open as a page

In JavaScript array destructuring, when does a default value like `const [a = 5] = values` actually apply — and what do you get when the matching element is null, a hole, or missing entirely?

level: juniorimportance: must knowfreq 72%
basics
~20 s

A destructuring default fires only when the matched value is exactly undefined — a missing index, an array hole, or an explicit undefined. null, 0, empty string and NaN are real values, so they are bound as-is.

open as a page

In JavaScript, what do Array.prototype.find and Array.prototype.findIndex return when no element satisfies the predicate, and what bug does that difference commonly cause?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Array.prototype.find returns undefined when nothing matches, while findIndex returns -1. The bug is truthiness: -1 is truthy and index 0 is falsy, so testing findIndex's result directly inverts the check. Compare it against -1 instead.

open as a page

Why does [10, 9, 1].sort() return [1, 10, 9] in JavaScript, and how do you sort an array of numbers correctly?

level: juniorimportance: must knowfreq 85%
basics
~20 s

Array.prototype.sort called with no comparator converts every element to a string and compares those strings, so "10" sorts before "9". Pass a numeric comparator, arr.sort((a, b) => a - b), to order numbers by value.

open as a page

In JavaScript, what is the difference between Array.prototype.map and Array.prototype.filter, and what does each one return?

level: juniorimportance: must knowfreq 82%
basics
~20 s

Array.prototype.map builds a new array of the same length by replacing each element with whatever its callback returns. Array.prototype.filter builds a new array holding only the elements whose callback returned a truthy value. Neither changes the original array.

open as a page

What does the JavaScript expression `new Date(2025, 0, 31)` represent, and which of the Date constructor's argument conventions most often cause off-by-one bugs?

level: juniorimportance: must knowfreq 72%
basics
~20 s

new Date(2025, 0, 31) is 31 January 2025 at local midnight. The month argument is zero-indexed (0 = January) while day-of-month starts at 1, and multi-argument construction is always read in the host's local time zone.

open as a page

Which built-in error constructors does JavaScript itself throw at runtime — TypeError, ReferenceError, RangeError, SyntaxError, URIError — and what kind of failure does each one signal?

level: juniorimportance: must knowfreq 72%
basics
~20 s

JavaScript throws TypeError when a value is the wrong kind of thing for the operation, ReferenceError when an identifier does not resolve, RangeError when a value of the right type is out of range, SyntaxError when source cannot be parsed, and URIError for malformed URI escapes.

open as a page

In JavaScript, which values are legal after `throw`, and what concretely breaks in the catching code when a function throws the string 'Network unavailable' instead of `new Error('Network unavailable')`?

level: juniorimportance: must knowfreq 72%
basics
~20 s

JavaScript's throw accepts any value: strings, numbers, plain objects, null, even undefined. Only Error instances carry name, message and a stack, so a thrown string leaves the catch block with no diagnostics, err.message undefined, and err instanceof Error false.

open as a page

In JavaScript, when does a `finally` block actually run? Does it still execute if the `try` block returns a value, or if an error is thrown that no `catch` clause handles?

level: juniorimportance: must knowfreq 75%
basics
~20 s

A JavaScript finally block runs on every exit from its try statement - normal completion, an early return, a break or continue, a caught error, and an error still propagating outward - which is exactly why cleanup belongs there.

open as a page

What does JSON.stringify() do with undefined, function values and symbols, and how does the outcome differ between an object property, an array element, and the top-level argument?

level: juniorimportance: must knowfreq 75%
basics
~20 s

JSON.stringify silently drops undefined, function and symbol object properties, turns those same values into null inside arrays, and returns the value undefined — not a string — when you pass one directly as the top-level argument.

open as a page