Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

API reference

JS Puzzles API reference

tricky JavaScript puzzles and gotchas

Identifiers
100
With full guides
95
Types
1

Topics covered

  • Hoisting traps
  • this binding puzzles
  • Type coercion quirks
  • Closures in loops
  • Array holes & sort
  • NaN & equality
  • Floating-point math
  • Async ordering

Const

NameWhat it does
HoistingHoisting is the observable behavior in which JavaScript makes certain declarations available before their source position executes. Its effects differ: var reads as undefined, function declarations are callable, and let/const remain inaccessible in the temporal dead zone.
ClosuresClosures let functions retain access to variables from the lexical environment where they were created. This supports persistent state, private data, and callbacks that run after their surrounding function has finished.
this bindingJavaScript’s this for regular functions comes from the call form, not the definition. Use bind to create a callable function with a fixed this and optional initial arguments.
Type coercionType coercion is JavaScript's automatic or implicit conversion from one data type to another. It explains why operations such as addition may produce a string or number depending on the operands.
Event loopThe event loop coordinates JavaScript's asynchronous work: it runs one macrotask, drains all microtasks, may render, and then continues with the next macrotask. This ordering explains why promise callbacks commonly precede zero-delay timers.
Prototype chainJavaScript resolves a missing property by searching the object's prototype, then that prototype's prototype, until it finds a match or reaches null. This linked lookup structure is the prototype chain.
Temporal dead zoneThe temporal dead zone is the interval from entering a block until execution initializes a let, const, or class binding. Accessing the binding during that interval throws a ReferenceError.
NaN equalityNaN is unequal to every value, including itself, under == and ===. Detect it with Number.isNaN() rather than an equality comparison.
Temporal Dead ZoneThe temporal dead zone is the interval after a lexical binding's scope starts but before execution initializes its let, const, or class declaration. Reading the binding during that interval throws a ReferenceError.
Type CoercionJavaScript automatically converts values when an operation expects another type. The conversion path depends on the context and can involve primitive, numeric, BigInt, string, or object-to-primitive rules.
NaN behaviorNaN represents an invalid or undefined numerical result. It is unequal to every value, usually propagates through arithmetic, and should be tested with Number.isNaN() rather than equality.
Event LoopThe JavaScript event loop processes macrotasks one at a time, then drains all pending microtasks before rendering and moving to the next macrotask. This ordering governs scripts, timers, user events, and Promise callbacks.
Microtask QueueThe microtask queue is the internal PromiseJobs queue used for promise handlers. Handlers are queued asynchronously and run in FIFO order after the current synchronous code finishes.
Prototype ChainJavaScript resolves missing properties by walking an object's prototype chain. The chain ends at null; if no object provides the property, the result is undefined.
AutoboxingJavaScript primitives can use methods because the language temporarily wraps them in corresponding objects. The primitive remains unchanged; null and undefined are exceptions.
Floating Point PrecisionJavaScript numbers use IEEE 754 double-precision binary floating point, so decimal arithmetic can contain small representation errors. Compare results with a tolerance suited to their magnitude instead of relying on strict equality.
typeof nulltypeof null returns "object", even though null is a separate JavaScript type and is not an object. This historical behavior is retained for compatibility.
Array holesArray holes are missing indexed properties, not stored undefined values. They make an array sparse, and different operations either skip the missing positions or expose them as undefined.
Numeric SeparatorsNumeric separators are underscores placed between digits in a number literal, such as 1_000_000. They improve readability while leaving the represented numeric value unchanged.
Optional ChainingOptional chaining (?.) safely accesses nested properties, computed properties, or methods when a value may be null or undefined. It short-circuits that chain and returns undefined instead of throwing.
Tagged TemplatesConst
Label StatementsA label names a loop so nested break or continue can target that loop. It provides structured control flow, not an arbitrary jump mechanism.
Comma OperatorThe comma operator evaluates several expressions from left to right and returns only the last expression's value. Parentheses are often needed because comma has very low precedence.
void operatorThe void operator evaluates an expression, discards its result, and returns undefined. Parenthesize complex operands to make operator precedence explicit.
Bitwise TricksJavaScript bitwise operators manipulate the binary representation of 32-bit integer operands. They include logical bit operations and left or right shifts, and are mainly useful for specialized low-level tasks.
parseInt radixparseInt(str, radix) reads an integer prefix using the specified base, from 2 through 36. It stops at the first character that is not valid in that base and returns the digits read so far.
Number.MAX_SAFE_INTEGERNumber.MAX_SAFE_INTEGER is the Number static property equal to 9007199254740991 (2^53 − 1). It is the greatest integer JavaScript can represent exactly and compare reliably as a Number.
Equality TableJavaScript has three main value-comparison operations: ==, ===, and Object.is(). Their results differ mainly in coercion, NaN handling, and the treatment of signed zero.
Truthy and FalsyJavaScript converts values to Boolean in conditions and logical expressions. Most values are truthy; false, zero, the empty string, null, undefined, and NaN are falsy.
Spread vs RestRest parameters gather remaining function arguments into an array, while spread syntax expands an iterable into separate arguments or elements. Both use ..., but their syntactic position determines which behavior applies.
Destructuring DefaultsConst
Generator return valueA generator's return(value) ends generator execution and supplies a final value. The caller sees it in the result of next() with done: true, unlike ordinary yielded values.
Symbol.toPrimitiveSymbol.toPrimitive is a well-known symbol used to define an object's conversion to a primitive. JavaScript calls the associated method with a hint before falling back to valueOf() and toString().
IIFEConst
CurryingCurrying transforms a multi-argument function so it can be called through successive calls such as f(a)(b)(c). The wrapper collects arguments and invokes the original function when enough have been supplied.
MemoizationMemoization caches a function's result for an input so repeated calls can avoid recalculation. In JavaScript, it is commonly implemented as a decorator backed by a Map.
Debouncedebounce(f, ms) returns a wrapper that waits until calls stop for ms milliseconds, then invokes f once with the latest arguments. New calls cancel the previous scheduled invocation.
Throttlethrottle(f, ms) creates a wrapper that invokes f at most once per interval. It runs the first call immediately and later forwards the latest call after the cooldown.
Deep vs Shallow CopyA shallow copy creates a new outer object but keeps references to nested objects. A deep copy recursively duplicates nested properties; structuredClone is the documented built-in for this purpose.
Pass by ReferenceJavaScript passes arguments by value, not by reference. For object arguments, the copied value still identifies the same object, so property mutations are visible to the caller while parameter reassignment is local.
Variable ShadowingVariable shadowing happens when a nested scope declares a name already used outside it. With const, the inner binding takes precedence throughout the block and is inaccessible before initialization.
Block Scopeconst creates a block-scoped binding that must be initialized immediately and cannot be reassigned. The referenced object or array may still be mutated.
Function ScopeFunction scope limits a function's local declarations to that function. Nested functions can access enclosing scopes, creating a scope chain where nearer bindings shadow outer ones.
Lexical ScopeLexical scope determines where JavaScript resolves names: from the current lexical environment outward through its enclosing environments. Blocks, functions, and scripts form environments, with let and const providing block-scoped bindings.
Dynamic thisJavaScript's regular-function this is determined by how the function is called, not where it is defined. Method calls provide the receiver, while standalone calls, explicit binding, constructors, and arrow functions follow different rules.
Arrow function thisArrow functions do not have their own this; they read it from the surrounding context. This makes them useful as callbacks inside methods when the callback must preserve the method's object context.
new.targetnew.target reveals whether the current function was called with new. It is undefined for regular calls and refers to the function during construction.
Tail CallA tail call is a final function call with no work left for the caller. Tail-call optimization can reduce stack usage for suitable recursion, but JavaScript engine support is not universal.
Short Circuit EvaluationShort-circuit evaluation makes JavaScript stop evaluating a logical expression as soon as its result is determined. The || operator stops at a truthy value, while && stops at a falsy value, and each returns the operand where it stopped.
Nullish CoalescingThe ?? operator returns its left value unless it is null or undefined, in which case it returns the right value. It is commonly used for defaults while preserving meaningful falsy values such as 0, false, and ''.
Logical AssignmentLogical assignment operators conditionally assign values using ||=, &&=, or ??=. They short-circuit, so the right-hand expression runs only when assignment is needed.
Array.prototype.sort defaultArray.prototype.sort() rearranges an array in place and returns the same array. Without a comparator, it compares string representations by UTF-16 code units, so numeric values require an explicit numeric comparator.
Map vs ObjectMap is a keyed collection like Object, but it accepts keys of any type, including objects, and provides convenient methods plus size. Use it for dynamic keyed data; use Object when the shape and string-like keys are known in advance.
Set uniquenessA Set is a collection of values without keys where each value appears at most once. It is useful for membership checks and removing duplicates.
Object key orderJavaScript objects use a special key order: integer property names come first in ascending numeric order, while other string keys follow creation order. Thus, object enumeration is not always simple insertion order.
JSON pitfallsJSON.stringify converts JavaScript values to JSON text, and JSON.parse converts JSON text back into JavaScript values. JSON supports fewer types than JavaScript, so serialization can omit unsupported data.
Date parsingDate.parse(str) reads a date from a string and returns its timestamp in milliseconds since 1 January 1970 UTC. Invalid formats produce NaN.
Regex lastIndexRegExp.lastIndex records where the next search starts for global and sticky regular expressions. Successful matches advance it, while failed exec() calls reset it to 0; assigning it manually selects a starting offset.
String immutabilityJavaScript strings are immutable: once created, their contents cannot be changed. String operations return new strings, so retain the result when you need transformed text.
Implicit globalsConst
Strict ModeStrict mode is enabled with the "use strict" directive at the top of a script or function. It changes JavaScript to a stricter execution mode; classes and modules enable it automatically.
getter and setterGetters and setters create accessor properties that look like ordinary fields to callers. Reads invoke the getter, while assignments invoke the setter.
Property descriptorsProperty descriptors describe an object's property value and its writable, enumerable, and configurable flags. JavaScript provides methods to inspect descriptors and create or update properties with precise behavior.
Object.freezeObject.freeze() prevents extensions and makes an object's existing properties non-writable and non-configurable. It returns the same object, while nested objects remain mutable unless frozen separately.
Object.sealObject.seal(obj) prevents adding or removing properties and makes existing properties non-configurable. Writable existing values can still change.
Symbol uniquenessJavaScript symbols are primitive unique identifiers. Separate Symbol() calls stay distinct even with the same description, while Symbol.for(key) reuses a symbol from the global registry.
WeakMap GCWeakMap associates values with object keys without preventing those keys from being garbage-collected. Its entries cannot be enumerated, and cleanup timing is controlled by the JavaScript engine.
Promise resolution orderPromise handlers are deferred to the microtask queue, even when a promise is already settled. They run after current synchronous code and in FIFO order, before the event loop advances to later macrotasks.
async await orderingasync functions return promises, and await pauses only the surrounding function. After the awaited promise settles, execution continues asynchronously through the microtask queue, so caller code and other microtasks can run first.
setTimeout 0setTimeout(func, 0) schedules a callback as soon as possible, but only after the current script completes. It does not mean the callback runs immediately or exactly zero milliseconds later.
requestAnimationFramerequestAnimationFrame schedules an animation callback for the browser's next suitable animation opportunity. The callback receives elapsed time in milliseconds, and its returned request ID can be used to cancel the scheduled call.
Recursion limitsJavaScript engines cap the number of nested recursive calls because each call uses stack space. The exact limit varies by engine, and exceeding it can raise a maximum-stack-size error.
Stack vs HeapConst
Garbage CollectionJavaScript automatically reclaims objects that are no longer reachable from roots. The page explains reachability and the mark-and-sweep algorithm, including how cycles can be collected.
Function.lengthFunction.length is a numeric property that indicates how many formal parameters a function expects. Defaults stop the count, destructuring counts once, and rest parameters are excluded.
arguments objectThe arguments object is an array-like, iterable collection of every value supplied to a traditional function. It supports indexes and length, but not Array methods, and arrow functions inherit arguments from an enclosing normal function.
rest parametersRest parameters let a function accept any number of arguments by gathering the remaining arguments into an array. They are written with ... before the final parameter name.
default parameter scopeDefault parameter initializers run in their own scope, outside the function body. Earlier parameters are visible, but declarations in the body are not and can cause a runtime ReferenceError.
computed property namesComputed property names let object literals derive keys from evaluated expressions. Put the expression in square brackets to create a dynamic property name.
getter memoizationA memoized getter computes a property value on first access and caches it for subsequent reads. It combines lazy evaluation with property-level memoization.
Array.from iterablesArray.from turns an iterable or array-like value into a real array. It can also transform each item while building that array.
Iterator protocolThe iterator protocol standardizes objects that produce sequence values through next(). Each call returns an IteratorResult with value and done, while the iterable protocol lets language constructs obtain the iterator.
Generator delegationyield* composes generators by delegating iteration from an outer generator to an inner generator. The inner generator’s yielded values pass through transparently, and its final return value becomes the yield* expression’s result.
async generatorsAsync generators produce sequences lazily while allowing asynchronous work between values. Declare them with async function* and consume them using for await...of.
for-await-offor await...of processes values from an async iterable as they become available. It is the asynchronous counterpart of for...of and is commonly paired with async generators.
Proxy trapsJavaScript Proxy traps let a handler intercept fundamental operations on a target, such as property access, assignment, deletion, calls, and construction. Traps can customize behavior or delegate transparently to the target.
Reflect methodsReflect exposes function-based forms of interceptable object operations, with method names matching Proxy traps. It is commonly used in proxy handlers to forward the default operation after adding custom behavior.
BigInt arithmeticBigInt is JavaScript’s integer type for values of arbitrary length. Its arithmetic resembles Number arithmetic, but operands cannot be mixed with regular numbers and division truncates toward zero.
Number coercion tableNumber coercion converts JavaScript values to numbers using type-specific rules. Numbers pass through, primitive values map predictably, strings are parsed, and some values produce NaN or throw.
String coercionString coercion converts a value to text when JavaScript needs its string form. It happens implicitly in suitable operations or explicitly with String(value).
Boolean coercionJavaScript coerces values to booleans in conditions and other Boolean contexts. Only a small set of values is falsy; every other value is truthy.
Array flatteningUse flat() to create a new array with nested arrays concatenated to a chosen depth. Use flatMap() when transforming elements and flattening the results by one level in one operation.
Chained optional callsOptional chaining safely accesses nested properties and optionally calls methods when an intermediate value may be null or undefined. A nullish value before ?. short-circuits the remaining chain and returns undefined.
Ternary associativityJavaScript’s conditional (ternary) operator selects one of two values from a condition. Chained ? expressions are grouped right-to-left, enabling compact multi-condition selection.
Operator precedenceOperator precedence determines the default order for applying operators in a JavaScript expression. Higher precedence runs first, equal precedence proceeds left to right, and parentheses can override the order.
Exponentiation operatorThe exponentiation operator ** raises a base to an exponent, including fractional exponents. It is right-associative, so chained expressions group from the right.
Unary plusUnary plus (+) is the one-operand form of the plus operator. It leaves numbers unchanged and converts non-number operands to numbers, like Number(...).
Double negationDouble negation (!!) converts any JavaScript value to a boolean primitive using its truthiness. It is equivalent to Boolean(value).
Comma in arraysA trailing comma after the last item in an array literal is allowed and ignored. It keeps multiline array edits consistent, but additional commas create sparse-array holes.
Trailing commasTrailing commas may follow the final item in many JavaScript comma-separated lists. They are optional, preserve semantics, and make multiline edits cleaner, but JSON and rest parameters have different rules.

Search across every package and filter by type in your dashboard.

Start learning