[{"data":1,"prerenderedAt":743},["ShallowReactive",2],{"topic-javascript-functions":3},{"framework":4,"topic":15,"subtopics":24},{"id":5,"description":6,"extension":7,"icon":8,"meta":9,"name":10,"order":11,"slug":8,"stem":12,"tier":13,"__hash__":14},"frameworks\u002Fframeworks\u002Fjavascript.yml","Core JavaScript interview questions covering fundamentals, functions and closures, objects and prototypes, classes and OOP, and asynchronous programming with the event loop.","yml","javascript",{},"JavaScript",1,"frameworks\u002Fjavascript",0,"_TjxyYWBq7dftU9YakX_WX1Z4wAHq9uEUUW7wXL0y0c",{"id":16,"description":17,"extension":7,"frameworkSlug":8,"meta":18,"name":19,"order":20,"slug":21,"stem":22,"__hash__":23},"topics\u002Ftopics\u002Fjavascript-functions.yml","Closures, the `this` keyword, arrow vs regular functions and higher-order functions — the most heavily tested JavaScript topic.",{},"Functions",2,"functions","topics\u002Fjavascript-functions","MW3Vo2V6aTP440PSUUciwdZ8aQGq4v2H0YF_E9en9vU",[25,184,331,471,607],{"id":26,"title":27,"body":28,"description":32,"difficulty":34,"extension":35,"framework":10,"frameworkSlug":8,"meta":36,"navigation":37,"order":11,"path":38,"questions":39,"related":178,"seo":179,"seoDescription":180,"stem":181,"subtopic":27,"topic":19,"topicSlug":21,"updated":182,"__hash__":183},"qa\u002Fjavascript\u002Ffunctions\u002Fclosures.md","Closures",{"type":29,"value":30,"toc":31},"minimark",[],{"title":32,"searchDepth":20,"depth":20,"links":33},"",[],"medium","md",{},true,"\u002Fjavascript\u002Ffunctions\u002Fclosures",[40,44,48,53,57,61,65,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174],{"id":41,"difficulty":34,"q":42,"a":43},"what-is-closure","What is a closure?","A closure is a function bundled together with a **reference to the lexical\nscope in which it was created**. Because of that bundle, the inner function\nkeeps access to its outer variables **even after the outer function has\nreturned** and that outer call's scope would otherwise be gone.\n\n```js\nfunction counter() {\n  let count = 0           \u002F\u002F lives in counter's scope\n  return () => ++count    \u002F\u002F this arrow closes over `count`\n}\n\nconst next = counter()    \u002F\u002F counter() has returned...\nnext() \u002F\u002F 1               \u002F\u002F ...yet `count` is still alive and remembered\nnext() \u002F\u002F 2\n```\n\nThe key insight interviewers want: the closure captures the **variable itself\n(the binding), not a copy of its value**. So `count` is genuinely shared and\nmutable across calls — each `next()` sees and updates the same `count`. Every\nfunction in JavaScript is technically a closure; it only *matters* when the\nfunction outlives the scope it captured.\n",{"id":45,"difficulty":34,"q":46,"a":47},"closure-use","What are practical uses of closures?","Closures are everywhere in real JavaScript, usually to **remember state\nbetween calls** without a global variable or a class:\n\n- **Data privacy \u002F encapsulation** — the module pattern, private counters,\n  anything you don't want callers to touch directly.\n- **Function factories & currying \u002F partial application** — pre-fill some\n  arguments and return a specialized function.\n- **Callbacks & event handlers** — a handler remembers the data it was set up\n  with.\n- **Memoization** — keep a private cache between invocations.\n\n```js\nfunction memoize(fn) {\n  const cache = new Map()        \u002F\u002F private, persists across calls\n  return arg => {\n    if (cache.has(arg)) return cache.get(arg)\n    const result = fn(arg)\n    cache.set(arg, result)\n    return result\n  }\n}\n```\n",{"id":49,"difficulty":50,"q":51,"a":52},"closure-memory","hard","Can closures cause memory leaks?","Yes. A closure keeps its captured scope alive for as long as the closure\nitself is reachable. If that closure outlives its usefulness while holding\nreferences to **large objects or detached DOM nodes**, the garbage collector\ncan't reclaim them — a leak.\n\n```js\nfunction attach() {\n  const huge = new Array(1_000_000).fill('🐘')\n  document.getElementById('btn').addEventListener('click', () => {\n    \u002F\u002F this handler closes over `huge`, pinning it in memory forever\n    console.log(huge.length)\n  })\n}\n```\n\nMitigations: remove event listeners when you're done\n(`removeEventListener`), null out references you no longer need, avoid\ncapturing more than necessary, and consider `WeakMap`\u002F`WeakRef` for caches so\nentries can be collected when nothing else references the key.\n",{"id":54,"difficulty":50,"q":55,"a":56},"closure-loop","How do closures explain the classic for-loop var bug?","With `var`, the loop variable is **function-scoped**, so there's a *single*\nbinding shared by every iteration. By the time the deferred callbacks run, the\nloop has finished and they all read that one binding's **final value**. `let`\nis **block-scoped** and creates a **fresh binding per iteration**, so each\ncallback closes over its own copy.\n\n```js\n\u002F\u002F all share one `i`, which is 3 when the timeouts fire\nfor (var i = 0; i \u003C 3; i++) setTimeout(() => console.log(i)) \u002F\u002F 3 3 3\n\n\u002F\u002F a new `i` per iteration\nfor (let i = 0; i \u003C 3; i++) setTimeout(() => console.log(i)) \u002F\u002F 0 1 2\n```\n\nBefore `let` existed, the fix was to create a new scope manually with an IIFE:\n`(j => setTimeout(() => console.log(j)))(i)`. This question is really testing\nwhether you understand *binding vs value* capture.\n",{"id":58,"difficulty":34,"q":59,"a":60},"private-vars","How do you create private variables with closures?","Declare variables in an enclosing function scope and return only the functions\nthat should be allowed to touch them. The variables are unreachable from\noutside — there's no reference to them except through the methods you exposed.\n\n```js\nfunction account() {\n  let balance = 0 \u002F\u002F truly private — no outside access\n  return {\n    deposit: n => (balance += n),\n    withdraw: n => (balance -= n),\n    get: () => balance,\n  }\n}\n\nconst a = account()\na.deposit(100)\na.get()       \u002F\u002F 100\na.balance     \u002F\u002F undefined — can't reach the closed-over variable\n```\n\nThis was the canonical way to get encapsulation before JavaScript added\n`#private` class fields, and it still underlies the module pattern.\n",{"id":62,"difficulty":34,"q":63,"a":64},"currying","What is currying and how do closures enable it?","Currying transforms a function that takes **many arguments** into a **chain of\nfunctions that each take one**. Closures make it work: each returned function\n*remembers* the arguments supplied to the earlier ones via its captured scope.\n\n```js\nconst add = a => b => c => a + b + c\nadd(1)(2)(3) \u002F\u002F 6\n\n\u002F\u002F practical: build specialized functions by partially applying\nconst multiply = a => b => a * b\nconst double = multiply(2) \u002F\u002F remembers a = 2\ndouble(10) \u002F\u002F 20\n```\n\nEach inner arrow closes over the parameters of the outer arrows, which is why\n`double` keeps `a = 2` ready for whenever you call it. Useful for\nconfiguration, reusable utilities, and point-free function composition.\n",{"id":66,"difficulty":67,"q":68,"a":69},"iife","easy","What is an IIFE and why was it used?","An **Immediately Invoked Function Expression** is a function that runs the\ninstant it's defined — you wrap it in parentheses to make it an *expression*\nand immediately call it with `()`.\n\n```js\n(function () {\n  const secret = 42 \u002F\u002F scoped to here, not global\n  console.log(secret)\n})()\n```\n\nBefore block scoping (`let`\u002F`const`) and ES modules, the IIFE was the main tool\nfor creating a **private scope**: it kept variables out of the global namespace\n(avoiding name collisions between scripts) and was the backbone of the module\npattern. Today `let`\u002F`const` blocks and real modules cover most of these cases,\nso you see IIFEs less often.\n",{"id":71,"difficulty":34,"q":72,"a":73},"closure-vs-scope","What is the difference between scope and a closure?","They're related but not the same thing:\n\n- **Scope** is a *static* concept: the set of variables accessible at a given\n  location in your code, determined by where things are written (lexical\n  scoping). It exists whether or not any function \"leaves.\"\n- A **closure** is what you get at *runtime* when a function **retains access to\n  its defining scope and carries it along** to be executed somewhere else —\n  after the outer function has returned.\n\n```js\nfunction outer() {\n  const x = 10        \u002F\u002F x is in outer's SCOPE\n  return () => x      \u002F\u002F the returned function + its hold on x = a CLOSURE\n}\nconst fn = outer()    \u002F\u002F outer's scope is gone, but the closure keeps x alive\nfn() \u002F\u002F 10\n```\n\nPut simply: scope defines *what a function can see*; a closure is the function\n*remembering and preserving* that view beyond its original lifetime.\n",{"id":75,"difficulty":34,"q":76,"a":77},"module-pattern","What is the module pattern?","The module pattern uses a closure (classically an IIFE) to create **private\nstate** and expose only a public API — the returned object's methods close over\nvariables that are otherwise inaccessible.\n\n```js\nconst counter = (function () {\n  let count = 0                  \u002F\u002F private\n  return {\n    increment() { count++ },\n    value() { return count },\n  }\n})()\ncounter.increment()\ncounter.value()  \u002F\u002F 1\ncounter.count    \u002F\u002F undefined — truly private\n```\n\nIt was the standard way to organize code and hide internals before ES modules.\nToday `import`\u002F`export` modules serve the same purpose at the file level, but the\npattern still appears for encapsulated singletons.\n",{"id":79,"difficulty":50,"q":80,"a":81},"debounce","How do you implement debounce with a closure?","Debounce delays running a function until input **stops** for a quiet period. A\nclosure holds the pending timer id across calls so each new call can cancel the\nprevious one.\n\n```js\nfunction debounce(fn, delay) {\n  let timer                      \u002F\u002F remembered between calls via closure\n  return function (...args) {\n    clearTimeout(timer)\n    timer = setTimeout(() => fn.apply(this, args), delay)\n  }\n}\nconst onSearch = debounce(query => fetchResults(query), 300)\n```\n\nEach keystroke resets the timer; `fn` runs only 300ms after the **last** call.\nThe private `timer` variable is exactly the kind of persistent state closures\nexist for.\n",{"id":83,"difficulty":50,"q":84,"a":85},"throttle","How does throttle differ from debounce, and how do you implement it?","**Throttle** runs the function **at most once per interval** (regular cadence),\nwhereas **debounce** waits until activity stops. A closure tracks the last run\ntime.\n\n```js\nfunction throttle(fn, limit) {\n  let last = 0\n  return function (...args) {\n    const now = Date.now()\n    if (now - last >= limit) {\n      last = now\n      fn.apply(this, args)\n    }\n  }\n}\nconst onScroll = throttle(() => updatePosition(), 100)\n```\n\nUse **throttle** for continuous events where you want steady updates (scroll,\nresize, mousemove); use **debounce** for \"act after they finish\" (search input,\nautosave).\n",{"id":87,"difficulty":34,"q":88,"a":89},"once","How do you write a once() function?","`once` wraps a function so it runs **only the first time** and returns the cached\nresult thereafter. A closure remembers whether it has been called and the result.\n\n```js\nfunction once(fn) {\n  let called = false, result\n  return function (...args) {\n    if (!called) {\n      called = true\n      result = fn.apply(this, args)\n    }\n    return result\n  }\n}\nconst init = once(() => console.log('init!'))\ninit() \u002F\u002F 'init!'\ninit() \u002F\u002F (nothing — cached)\n```\n\nUseful for one-time initialization, idempotent event handlers, and lazy\nsingletons.\n",{"id":91,"difficulty":50,"q":92,"a":93},"memoize","How do you implement memoization with a closure?","Memoization caches results of expensive pure functions by their arguments. A\nclosure holds a private cache that persists across calls.\n\n```js\nfunction memoize(fn) {\n  const cache = new Map()        \u002F\u002F private, lives between calls\n  return function (...args) {\n    const key = JSON.stringify(args)\n    if (cache.has(key)) return cache.get(key)\n    const result = fn.apply(this, args)\n    cache.set(key, result)\n    return result\n  }\n}\nconst slowSquare = memoize(n => n * n)\n```\n\nThe cache is invisible to callers — pure encapsulation. Only memoize **pure**\nfunctions, and mind cache growth (a `WeakMap` or LRU cap helps for large key\nspaces).\n",{"id":95,"difficulty":34,"q":96,"a":97},"partial-application","What is partial application and how do closures enable it?","Partial application **fixes some arguments** of a function now, returning a new\nfunction that takes the rest later. The returned function closes over the\npre-supplied arguments.\n\n```js\nfunction partial(fn, ...preset) {\n  return (...rest) => fn(...preset, ...rest) \u002F\u002F closes over `preset`\n}\nconst add = (a, b, c) => a + b + c\nconst add10 = partial(add, 10)\nadd10(20, 30) \u002F\u002F 60\n```\n\nIt differs from currying (which takes args one at a time); partial application\nfixes any number at once. Both rely on closures to remember the bound arguments.\n",{"id":99,"difficulty":34,"q":100,"a":101},"event-handler-state","How do closures help event handlers keep state?","An event handler defined inside a function closes over that function's variables,\nso each handler \"remembers\" the data it was created with — without needing global\nstate or data attributes.\n\n```js\nfunction setupButtons(labels) {\n  labels.forEach((label, i) => {\n    button[i].addEventListener('click', () => {\n      console.log(`clicked ${label} (#${i})`) \u002F\u002F closes over label and i\n    })\n  })\n}\n```\n\nEach handler captures its own `label`\u002F`i`. (Using `let`\u002F`forEach` gives a fresh\nbinding per iteration — the same reason the classic `var` loop bug doesn't\nappear here.)\n",{"id":103,"difficulty":50,"q":104,"a":105},"settimeout-puzzle","What does this setTimeout-in-a-loop snippet print and why?","```js\nfor (var i = 0; i \u003C 3; i++) {\n  setTimeout(() => console.log(i), 100)\n}\n\u002F\u002F 3 3 3\n```\n\nAll three arrow functions close over the **same** `var i` (function-scoped). By\nthe time the timers fire (after the loop completes), `i` is `3`. Fixes:\n\n```js\nfor (let i = 0; i \u003C 3; i++) setTimeout(() => console.log(i), 100) \u002F\u002F 0 1 2\n\u002F\u002F or capture per iteration with an IIFE:\nfor (var i = 0; i \u003C 3; i++) ((j) => setTimeout(() => console.log(j)))(i)\n```\n\nThe lesson: closures capture the **variable binding**, not a snapshot of its\nvalue.\n",{"id":107,"difficulty":50,"q":108,"a":109},"capture-reference","Do closures capture a variable's value or the variable itself?","Closures capture the **variable (binding), not a copy of its value**. So if the\nvariable changes after the closure is created, the closure sees the **new**\nvalue.\n\n```js\nlet x = 1\nconst read = () => x\nx = 99\nread() \u002F\u002F 99 — not 1\n```\n\nThis is why the `var` loop bug happens (all closures share one binding) and why\n`let` fixes it (a fresh binding each iteration). To capture a value snapshot,\ncopy it into a new scope (an IIFE parameter or a `let` in the loop body).\n",{"id":111,"difficulty":34,"q":112,"a":113},"lexical-scoping","What is lexical scoping and how does it relate to closures?","Lexical (static) scoping means a function's accessible variables are determined by\n**where it is written** in the source, not where it's called. Closures are the\nruntime consequence: a function carries its lexical environment with it.\n\n```js\nfunction outer() {\n  const secret = 42\n  function inner() { return secret } \u002F\u002F resolves `secret` by lexical position\n  return inner\n}\nouter()() \u002F\u002F 42 — inner remembers outer's scope wherever it runs\n```\n\nBecause scope is fixed at definition time, you can reason about what a closure can\naccess just by reading the nested structure of the code.\n",{"id":115,"difficulty":34,"q":116,"a":117},"each-call-new-closure","Does each function call create a new closure?","Yes. Every invocation of an outer function creates a **fresh scope**, so any inner\nfunctions returned capture **independent** copies of that scope. Two calls to a\nfactory produce two unrelated states.\n\n```js\nfunction counter() { let n = 0; return () => ++n }\nconst a = counter()\nconst b = counter()\na() \u002F\u002F 1\na() \u002F\u002F 2\nb() \u002F\u002F 1 — separate closure, separate `n`\n```\n\nThis independence is what makes closure-based factories useful: each produced\nobject has its own private state.\n",{"id":119,"difficulty":67,"q":120,"a":121},"function-factory","What is a function factory?","A function factory is a function that **returns customized functions**, each\nclosing over the arguments used to create it. It's a clean way to generate\nspecialized variants.\n\n```js\nfunction makeMultiplier(factor) {\n  return n => n * factor   \u002F\u002F closes over `factor`\n}\nconst double = makeMultiplier(2)\nconst triple = makeMultiplier(3)\ndouble(5) \u002F\u002F 10\ntriple(5) \u002F\u002F 15\n```\n\nEach returned function remembers its own `factor`. Factories built on closures\npower currying, partial application, and configurable utilities.\n",{"id":123,"difficulty":50,"q":124,"a":125},"closures-and-this","Do closures capture this?","No — a closure captures **variables** from its lexical scope, but `this` is **not**\na normal variable for regular functions; it's set by how the function is called.\n**Arrow functions**, however, capture `this` lexically (like a closed-over\nvariable).\n\n```js\nconst obj = {\n  name: 'Ada',\n  regular() { return function () { return this.name } }, \u002F\u002F `this` lost\n  arrow()   { return () => this.name },                  \u002F\u002F `this` captured\n}\nobj.regular()() \u002F\u002F undefined (this is not obj)\nobj.arrow()()   \u002F\u002F 'Ada'  (arrow closes over obj's this)\n```\n\nA common pre-arrow workaround was `const self = this`, which *does* capture `this`\nas an ordinary closed-over variable.\n",{"id":127,"difficulty":34,"q":128,"a":129},"closure-vs-class","How do closures compare to classes for encapsulation?","Both can hide state. **Closures** give true privacy via captured variables, with\na functional feel and no `this`. **Classes** are more familiar, support\ninheritance and (now) `#private` fields, and are more memory-efficient when you\ncreate many instances (methods live once on the prototype).\n\n```js\n\u002F\u002F closure\nconst make = () => { let n = 0; return { inc: () => ++n } }\n\u002F\u002F class\nclass C { #n = 0; inc() { return ++this.#n } }\n```\n\nClosures excel for small factories and one-offs; classes scale better for many\ninstances and rich hierarchies. With `#private` fields, classes now match\nclosures on genuine privacy.\n",{"id":131,"difficulty":34,"q":132,"a":133},"revealing-module","What is the revealing module pattern?","A variation of the module pattern where you define all functions\u002Fvariables\nprivately and **return an object that maps public names to those private\nmembers** — making the public API explicit at the bottom.\n\n```js\nconst calc = (function () {\n  let total = 0\n  function add(n) { total += n }\n  function get() { return total }\n  return { add, get }   \u002F\u002F \"reveal\" only these\n})()\n```\n\nIt improves readability (the exposed surface is listed in one place) and lets you\nrename the public API independently of the private implementation.\n",{"id":135,"difficulty":50,"q":136,"a":137},"generator-vs-closure","How do generators compare to closures for maintaining state?","Both keep state between calls. A **closure** holds state in captured variables a\nreturned function reads\u002Fwrites. A **generator** pauses at `yield` and resumes,\npreserving its entire execution state — better for **sequences** and lazy\niteration.\n\n```js\n\u002F\u002F closure counter\nconst counter = (() => { let n = 0; return () => ++n })()\n\u002F\u002F generator counter\nfunction* gen() { let n = 0; while (true) yield ++n }\nconst g = gen()\ng.next().value \u002F\u002F 1\n```\n\nUse a closure for simple persistent state; a generator when you need to produce a\nstream of values or model a resumable process.\n",{"id":139,"difficulty":50,"q":140,"a":141},"closure-react-stale","How do closures cause stale values in callbacks (e.g. React)?","A callback closes over the variables from the moment it was **created**. If those\nvalues change later but the callback isn't recreated, it keeps using the old\n(\"stale\") snapshot.\n\n```js\nlet count = 0\nconst timer = setInterval(() => console.log(count), 1000) \u002F\u002F always logs 0\ncount = 5 \u002F\u002F the closure captured the binding, but in React each render has its own\n```\n\nIn React, each render creates new closures over that render's props\u002Fstate, so an\neffect or event handler with stale deps logs old values. Fixes: include the value\nin dependencies, use a functional updater, or read the latest from a `ref`.\n",{"id":143,"difficulty":50,"q":144,"a":145},"closure-gc","When is a closure's captured scope garbage collected?","A closure keeps its captured variables alive **as long as the closure itself is\nreachable**. Once nothing references the closure, the captured scope becomes\neligible for garbage collection.\n\n```js\nfunction make() {\n  const big = new Array(1e6)\n  return () => big.length\n}\nlet fn = make()  \u002F\u002F `big` is retained because fn closes over it\nfn = null        \u002F\u002F now `big` can be collected\n```\n\nEngines optimize by capturing only the variables actually used, but holding onto\nclosures (e.g. in a long-lived array or an un-removed event listener)\nindefinitely retains their scope — a common leak source.\n",{"id":147,"difficulty":34,"q":148,"a":149},"nested-closures","How do nested closures work?","An inner function can close over variables from **multiple enclosing scopes** at\nonce, walking up the scope chain. Each level's variables remain accessible.\n\n```js\nfunction a(x) {\n  return function b(y) {\n    return function c(z) {\n      return x + y + z   \u002F\u002F closes over x (from a) AND y (from b)\n    }\n  }\n}\na(1)(2)(3) \u002F\u002F 6\n```\n\nThis layered capture is exactly how currying works. The innermost function holds\nreferences to every outer scope it uses, keeping them all alive.\n",{"id":151,"difficulty":67,"q":152,"a":153},"closure-array-methods","How do closures appear in array method callbacks?","Callbacks passed to `map`\u002F`filter`\u002F`reduce` close over variables in their\nsurrounding scope, letting them reference outside data without extra parameters.\n\n```js\nfunction aboveThreshold(numbers, threshold) {\n  return numbers.filter(n => n > threshold) \u002F\u002F closes over `threshold`\n}\naboveThreshold([1, 5, 10], 4) \u002F\u002F [5, 10]\n```\n\nThe arrow remembers `threshold` from the enclosing function. This is closures at\nwork in everyday code, usually without anyone calling it \"a closure.\"\n",{"id":155,"difficulty":50,"q":156,"a":157},"shared-state-bug","What bug arises when closures unexpectedly share state?","If multiple closures capture the **same** variable (instead of separate\nbindings), they all see and mutate one shared value — leading to surprising\ncoupling, like the `var` loop bug.\n\n```js\n\u002F\u002F all handlers share one `config` object\nconst config = {}\nconst handlers = sources.map(() => () => use(config)) \u002F\u002F same config\n```\n\nTo give each closure its own state, create a fresh scope per closure (a factory\ncall, an IIFE, or a block-scoped `let`). Recognizing shared vs independent capture\nis key to debugging closure issues.\n",{"id":159,"difficulty":34,"q":160,"a":161},"closure-async-await","How do closures behave across async boundaries?","Variables captured by a closure remain valid **after** awaits and across async\ngaps — the closure keeps the scope alive. But beware capturing a value that\n**changes** during the wait.\n\n```js\nasync function process(items) {\n  for (const item of items) {\n    await save(item)\n    \u002F\u002F `item` is correctly captured per iteration (let\u002Fconst)\n  }\n}\n```\n\n`let`\u002F`const` loop variables give each iteration a fresh binding, so async\ncallbacks see the right value. With `var`, the shared binding would be stale by\nthe time the awaited work resumes.\n",{"id":163,"difficulty":67,"q":164,"a":165},"counter-with-operations","How do you build an encapsulated counter with multiple operations?","Return an object whose methods all close over the same private variable, so they\nshare controlled access to it while the outside world can't touch it directly.\n\n```js\nfunction createCounter(start = 0) {\n  let count = start\n  return {\n    increment: () => ++count,\n    decrement: () => --count,\n    reset: () => (count = start),\n    value: () => count,\n  }\n}\nconst c = createCounter(10)\nc.increment(); c.value() \u002F\u002F 11\n```\n\nAll four methods operate on one private `count`. This is the closure-based\nalternative to a class with a private field.\n",{"id":167,"difficulty":34,"q":168,"a":169},"closure-loop-fix-iife","How does an IIFE fix the var loop closure problem?","An IIFE creates a **new scope per iteration**, capturing the current value as a\nparameter so each callback closes over its own copy.\n\n```js\nfor (var i = 0; i \u003C 3; i++) {\n  (function (j) {\n    setTimeout(() => console.log(j), 100) \u002F\u002F j is this iteration's copy\n  })(i)\n}\n\u002F\u002F 0 1 2\n```\n\nThe IIFE is immediately invoked with `i`, binding it to the local `j`. This was\nthe standard pre-ES6 fix; today simply using `let` (which block-scopes per\niteration) is cleaner.\n",{"id":171,"difficulty":34,"q":172,"a":173},"closure-overhead","Do closures have a performance or memory cost?","Each closure retains its captured variables in memory for as long as it lives, so\ncreating **many** closures (e.g. a new function per array element in a hot loop)\nuses more memory than sharing one function. Modern engines optimize aggressively,\ncapturing only used variables.\n\n```js\n\u002F\u002F creates N closures, each retaining scope\nitems.map(item => () => process(item))\n```\n\nIn practice closures are cheap and the readability\u002Fencapsulation wins outweigh the\ncost — but in performance-critical code with huge numbers of closures, reusing\nfunctions or avoiding unnecessary capture can matter.\n",{"id":175,"difficulty":34,"q":176,"a":177},"closure-singleton","How do you implement a singleton with a closure?","An IIFE runs once and returns a single shared instance; the closure caches it so\nevery access returns the same object.\n\n```js\nconst config = (function () {\n  let instance\n  function create() { return { loadedAt: Date.now() } }\n  return {\n    get() {\n      if (!instance) instance = create() \u002F\u002F created once\n      return instance\n    },\n  }\n})()\nconfig.get() === config.get() \u002F\u002F true — same instance\n```\n\nThe private `instance` variable, hidden in the closure, guarantees a single\nshared object — the closure-based singleton pattern.\n",null,{"description":32},"JavaScript closure interview questions and answers — what closures are, how they capture variables, practical uses and common pitfalls.","javascript\u002Ffunctions\u002Fclosures","2026-06-17","fIkqXiaH8g__RSSbGGQQ3i6Y8gV63cRtxHtJRDtN9gg",{"id":185,"title":186,"body":187,"description":32,"difficulty":50,"extension":35,"framework":10,"frameworkSlug":8,"meta":191,"navigation":37,"order":20,"path":192,"questions":193,"related":178,"seo":326,"seoDescription":327,"stem":328,"subtopic":329,"topic":19,"topicSlug":21,"updated":182,"__hash__":330},"qa\u002Fjavascript\u002Ffunctions\u002Fthis-keyword.md","This Keyword",{"type":29,"value":188,"toc":189},[],{"title":32,"searchDepth":20,"depth":20,"links":190},[],{},"\u002Fjavascript\u002Ffunctions\u002Fthis-keyword",[194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270,274,278,282,286,290,294,298,302,306,310,314,318,322],{"id":195,"difficulty":34,"q":196,"a":197},"what-is-this","How is the value of `this` determined?","The single most important idea: in a regular function `this` is decided by\n**how the function is *called*, not where it's defined**. There are four\nbinding rules, in order of precedence:\n\n1. **`new` binding** — `new Fn()` -> `this` is the brand-new instance.\n2. **Explicit binding** — `fn.call(obj)`, `fn.apply(obj)`, `fn.bind(obj)` ->\n   `this` is the object you pass.\n3. **Implicit binding** — `obj.fn()` -> `this` is `obj` (the thing left of the\n   dot).\n4. **Default binding** — a plain `fn()` -> `this` is `undefined` in strict mode,\n   or the global object (`window`\u002F`globalThis`) in sloppy mode.\n\n```js\nfunction who() { return this }\nconst obj = { who }\nobj.who()            \u002F\u002F obj      (implicit)\nwho.call('hi')       \u002F\u002F 'hi'     (explicit)\nnew who()            \u002F\u002F {}       (new instance)\nwho()                \u002F\u002F undefined in strict mode\n```\n\nArrow functions are the exception — they ignore all four rules and inherit\n`this` lexically (next question).\n",{"id":199,"difficulty":34,"q":200,"a":201},"arrow-this","How does `this` work in arrow functions?","Arrow functions **don't have their own `this`**. They capture it\n**lexically** — from the enclosing scope at the moment they're *defined* — and\nthat binding can never be changed (even `call`\u002F`apply`\u002F`bind` can't reassign\nit). This makes them perfect for callbacks where you want to keep the\nsurrounding object's `this`.\n\n```js\nclass Timer {\n  seconds = 0\n  start() {\n    \u002F\u002F arrow inherits `start`'s `this` (the Timer instance)\n    setInterval(() => this.seconds++, 1000)\n\n    \u002F\u002F a regular function here would be called by the timer with\n    \u002F\u002F `this` === undefined, so `this.seconds` would throw\n  }\n}\n```\n\nThe flip side: because they lack their own `this`, arrows are a poor choice for\n**object methods that need to reference the object** (`this` would point to the\nouter scope, not the object) and they **cannot be used as constructors**.\n",{"id":203,"difficulty":34,"q":204,"a":205},"call-apply-bind","What is the difference between call, apply and bind?","All three let you **explicitly set `this`**; they differ in *when* they invoke\nand *how* they take arguments:\n\n- `fn.call(thisArg, a, b)` — invokes **immediately**, arguments passed\n  **individually**.\n- `fn.apply(thisArg, [a, b])` — invokes **immediately**, arguments passed as an\n  **array**.\n- `fn.bind(thisArg, a)` — does **not** invoke; returns a **new function** with\n  `this` (and any given args) **permanently** locked in.\n\n```js\nfunction greet(greeting, mark) {\n  return `${greeting}, ${this.name}${mark}`\n}\nconst user = { name: 'Ada' }\n\ngreet.call(user, 'Hi', '!')      \u002F\u002F 'Hi, Ada!'   (args listed)\ngreet.apply(user, ['Hi', '!'])   \u002F\u002F 'Hi, Ada!'   (args in array)\nconst greetAda = greet.bind(user) \u002F\u002F returns a function\ngreetAda('Hey', '.')             \u002F\u002F 'Hey, Ada.'\n```\n\nMemory aid: **A**pply = **A**rray; **bind** = \"remember for later.\" `bind` is\nthe usual fix for passing a method as a callback without losing its receiver.\n",{"id":207,"difficulty":50,"q":208,"a":209},"lost-this","Why does `this` become undefined when passing a method as a callback?","Because `this` is set at **call time** by the *call site*, and passing a method\nsomewhere else detaches it from its object. `setTimeout(obj.fn)` only copies\nthe **function** — the `obj.` context is lost, so when the timer later calls it\nas a plain function, `this` is `undefined` (strict) \u002F global (sloppy).\n\n```js\nconst counter = {\n  count: 0,\n  inc() { this.count++ },\n}\n\nsetTimeout(counter.inc, 100)        \u002F\u002F `this` is not `counter` -> throws\u002FNaN\n\nsetTimeout(counter.inc.bind(counter), 100)  \u002F\u002F bind the receiver\nsetTimeout(() => counter.inc(), 100)        \u002F\u002F arrow calls it ON counter\n```\n\nThis is exactly why React class components had to do\n`this.handleClick = this.handleClick.bind(this)` in the constructor — or use\nclass arrow-field methods, which sidestep the problem.\n",{"id":211,"difficulty":34,"q":212,"a":213},"new-binding","What does `this` refer to inside a constructor function?","When you call a function with `new`, JavaScript does four things: (1) creates a\nfresh empty object, (2) sets that object's prototype to the constructor's\n`.prototype`, (3) binds `this` to the new object inside the call, and (4)\nreturns that object automatically — **unless** the constructor explicitly\nreturns its own (non-primitive) object.\n\n```js\nfunction User(name) {\n  this.name = name      \u002F\u002F `this` is the new instance\n  \u002F\u002F no return needed — the instance is returned for you\n}\nconst u = new User('Ada')\nu.name \u002F\u002F 'Ada'\n\nfunction Weird() {\n  this.a = 1\n  return { b: 2 } \u002F\u002F returning an object overrides the default `this`\n}\nnew Weird() \u002F\u002F { b: 2 }  (the `this.a = 1` is discarded)\n```\n\nForgetting `new` is a classic bug: calling `User('Ada')` plainly runs default\nbinding, so `this` is the global object and you accidentally create a global\n`name`.\n",{"id":215,"difficulty":34,"q":216,"a":217},"this-strict","How does strict mode change `this` in a plain function call?","In **sloppy (non-strict) mode**, a plain function call defaults `this` to the\n**global object** (`window` \u002F `globalThis`). In **strict mode** — and inside ES\nmodules and class bodies, which are *always* strict — that same call leaves\n`this` as **`undefined`**.\n\n```js\nfunction show() { return this }\n\n\u002F\u002F sloppy mode\nshow() \u002F\u002F the global object\n\n\u002F\u002F strict mode\n'use strict'\nshow() \u002F\u002F undefined\n```\n\nThis is a feature, not a nuisance: with `undefined` you get a loud\n`TypeError` the moment you accidentally rely on default binding\n(`Cannot read properties of undefined`), instead of silently leaking\nproperties onto the global object. It surfaces \"I forgot to bind `this`\" bugs\nimmediately.\n",{"id":219,"difficulty":50,"q":220,"a":221},"this-precedence","What is the precedence order of the this binding rules?","When multiple rules could apply, they resolve in this order (highest first):\n\n1. **`new` binding** — `new Fn()` wins over everything.\n2. **Explicit binding** — `call`\u002F`apply`\u002F`bind`.\n3. **Implicit binding** — `obj.method()`.\n4. **Default binding** — plain `fn()` -> `undefined`\u002Fglobal.\n\n```js\nfunction f() { return this.id }\nconst obj = { id: 1, f }\nconst bound = f.bind({ id: 2 })\nobj.f()            \u002F\u002F 1 (implicit)\nbound()            \u002F\u002F 2 (explicit beats implicit)\nnew bound().id     \u002F\u002F undefined-> new beats bind (this is the new instance)\n```\n\nArrow functions sit outside this hierarchy entirely — they ignore all four rules\nand inherit `this` lexically.\n",{"id":223,"difficulty":34,"q":224,"a":225},"this-event-listener","What is this inside a DOM event listener?","In a **regular function** listener, `this` is the **element** the handler is\nattached to (the `currentTarget`). In an **arrow function**, `this` is inherited\nfrom the surrounding scope instead.\n\n```js\nbutton.addEventListener('click', function () {\n  this \u002F\u002F the button element\n})\nbutton.addEventListener('click', () => {\n  this \u002F\u002F whatever `this` was outside (NOT the button)\n})\n```\n\nSo use a regular function when you want `this` to be the element; use an arrow\n(and `e.currentTarget`) when you need the outer `this`. This trips people up when\nconverting handlers to arrows.\n",{"id":227,"difficulty":34,"q":228,"a":229},"this-foreach","How do you control this inside forEach and similar methods?","`forEach`, `map`, `filter`, etc. accept an optional **`thisArg`** second argument\nthat sets `this` for the callback. Alternatively, use an arrow function that\ninherits `this` lexically.\n\n```js\nconst obj = {\n  prefix: '>',\n  log(arr) {\n    arr.forEach(function (x) { console.log(this.prefix, x) }, this) \u002F\u002F thisArg\n    arr.forEach(x => console.log(this.prefix, x))                   \u002F\u002F arrow\n  },\n}\n```\n\nWithout the `thisArg` (or an arrow), a regular callback's `this` would be\n`undefined`\u002Fglobal, and `this.prefix` would throw. Arrows are the modern,\npreferred fix.\n",{"id":231,"difficulty":34,"q":232,"a":233},"method-borrowing","What is method borrowing?","Method borrowing uses `call`\u002F`apply` to invoke a method from one object **on**\nanother object that doesn't have it — by explicitly setting `this`. Classic for\narray-like objects.\n\n```js\nfunction sum() {\n  \u002F\u002F `arguments` is array-like, not a real array\n  return Array.prototype.reduce.call(arguments, (a, b) => a + b, 0)\n}\nsum(1, 2, 3) \u002F\u002F 6\n\nconst arrayLike = { 0: 'a', 1: 'b', length: 2 }\nArray.prototype.join.call(arrayLike, '-') \u002F\u002F 'a-b'\n```\n\nYou \"borrow\" `Array.prototype` methods for array-likes (`arguments`, NodeLists).\nModern code often uses `Array.from`\u002Fspread instead, but borrowing shows how `this`\ndecouples a method from its object.\n",{"id":235,"difficulty":34,"q":236,"a":237},"bind-partial","How does bind enable partial application?","Beyond setting `this`, `bind` lets you **pre-fill leading arguments**, returning a\nfunction that takes the rest — partial application.\n\n```js\nfunction multiply(a, b) { return a * b }\nconst double = multiply.bind(null, 2) \u002F\u002F a is fixed to 2\ndouble(5) \u002F\u002F 10\n\nconst log = console.log.bind(console, '[APP]')\nlog('started') \u002F\u002F [APP] started\n```\n\nThe `null` thisArg is common when you only care about pre-binding arguments, not\n`this`. The bound arguments are remembered via the bound function's internal\nstate.\n",{"id":239,"difficulty":50,"q":240,"a":241},"new-overrides-bind","Does the new operator override a bound this?","Yes. `new` takes precedence over `bind` — when you call `new` on a bound function,\n`this` is the **new instance**, not the value you bound. (Pre-bound **arguments**\nare still applied, though.)\n\n```js\nfunction Point(x, y) { this.x = x; this.y = y }\nconst BoundPoint = Point.bind({ ignored: true }, 10)\nconst p = new BoundPoint(20)\np.x \u002F\u002F 10 (bound arg kept)\np.y \u002F\u002F 20\n\u002F\u002F p is a fresh instance; the bound { ignored: true } this was ignored\n```\n\nThis is the one case where `bind`'s \"permanent\" `this` is overridden, reflecting\nthat `new` is the highest-precedence binding rule.\n",{"id":243,"difficulty":34,"q":244,"a":245},"this-callback-loss","Why is this lost when passing an object method as a callback?","Passing `obj.method` as a callback copies only the **function**, detaching it from\n`obj`. When the receiver later calls it as a plain function, implicit binding is\ngone, so `this` is `undefined`\u002Fglobal.\n\n```js\nconst user = { name: 'Ada', greet() { return this.name } }\nconst fn = user.greet\nfn()                       \u002F\u002F undefined — detached\nsetTimeout(user.greet, 0)  \u002F\u002F also detached\n\nsetTimeout(() => user.greet(), 0)     \u002F\u002F called ON user\nsetTimeout(user.greet.bind(user), 0)  \u002F\u002F bound\n```\n\nThe fix is to preserve the receiver via an arrow wrapper or `bind`.\n",{"id":247,"difficulty":34,"q":248,"a":249},"this-promise","What is this inside a promise .then callback?","A regular-function `.then` callback is invoked by the promise machinery with no\nreceiver, so `this` is `undefined` (strict) \u002F global. An **arrow** `.then`\ncallback inherits `this` from the enclosing scope.\n\n```js\nclass Loader {\n  url = '\u002Fapi'\n  load() {\n    fetch(this.url)\n      .then(r => r.json())\n      .then(data => this.handle(data)) \u002F\u002F arrow keeps `this` = the Loader\n  }\n  handle(data) {}\n}\n```\n\nUsing arrows in `.then` chains is the norm precisely so `this` stays the\nsurrounding object. A regular function there would lose it.\n",{"id":251,"difficulty":34,"q":252,"a":253},"this-in-class","How does this behave in class methods?","Inside a class method, `this` refers to the **instance** when called as\n`instance.method()`. But class bodies are **always strict**, so an extracted\nmethod called plainly has `this === undefined` (not the global object).\n\n```js\nclass Counter {\n  count = 0\n  inc() { this.count++ }\n}\nconst c = new Counter()\nconst f = c.inc\nf() \u002F\u002F TypeError: Cannot read properties of undefined\n\n\u002F\u002F fix with a class field arrow method:\nclass Counter2 { count = 0; inc = () => this.count++ }\n```\n\nArrow **class fields** bind `this` to the instance permanently, which is why\nthey're popular for handlers.\n",{"id":255,"difficulty":34,"q":256,"a":257},"this-module-top","What is this at the top level of a module or script?","It depends on the context. In a **classic script** (non-strict), top-level `this`\nis the **global object** (`window`). In an **ES module**, top-level `this` is\n**`undefined`** (modules are always strict and have their own scope). In **Node\nCommonScript** modules, it's `module.exports`.\n\n```js\n\u002F\u002F classic \u003Cscript>:  this === window\n\u002F\u002F ES module (type=\"module\" \u002F .mjs):  this === undefined\n\u002F\u002F Node CommonScript module:  this === module.exports\n```\n\nUse **`globalThis`** to reliably reference the global object across all of these\nenvironments.\n",{"id":259,"difficulty":50,"q":260,"a":261},"arrow-method-pitfall","Why shouldn't you use an arrow function as an object method?","An arrow method captures `this` from the **enclosing scope at definition time** —\nwhich for an object literal is the surrounding scope, **not the object**. So\n`this` won't be the object you expect.\n\n```js\nconst obj = {\n  name: 'Ada',\n  greet: () => `Hi, ${this.name}`, \u002F\u002F `this` is the outer scope, not obj\n}\nobj.greet() \u002F\u002F 'Hi, undefined'\n\nconst obj2 = { name: 'Ada', greet() { return `Hi, ${this.name}` } }\nobj2.greet() \u002F\u002F 'Hi, Ada'\n```\n\nUse **method shorthand** (a regular function) for object methods that reference\n`this`. Reserve arrows for callbacks where you *want* the outer `this`.\n",{"id":263,"difficulty":67,"q":264,"a":265},"globalthis","What is globalThis?","`globalThis` (ES2020) is a standardized way to access the **global object** in any\nJavaScript environment — `window` in browsers, `self` in workers, `global` in\nNode — without environment checks.\n\n```js\nglobalThis.myGlobal = 42\n\u002F\u002F before globalThis you needed:\nconst g = typeof window !== 'undefined' ? window\n        : typeof global !== 'undefined' ? global : self\n```\n\nIt removes the brittle feature-detection people used to write. Relevant to `this`\nbecause default-bound `this` in sloppy mode *is* this global object.\n",{"id":267,"difficulty":34,"q":268,"a":269},"this-destructuring","What happens to this when you destructure a method off an object?","Destructuring extracts the **function value** without its object, so calling it\nloses implicit binding — `this` becomes `undefined`\u002Fglobal, exactly like assigning\nthe method to a variable.\n\n```js\nconst { greet } = user\ngreet() \u002F\u002F `this` is not `user` -> likely a TypeError\n\n\u002F\u002F common real example: destructuring instance methods\nconst { increment } = counter\nincrement() \u002F\u002F detached\n```\n\nIf a method uses `this`, don't destructure it (or `bind` it first). This bites\npeople destructuring class instances or React class methods.\n",{"id":271,"difficulty":34,"q":272,"a":273},"this-settimeout","What is this inside a setTimeout callback?","A regular-function `setTimeout` callback is invoked by the timer with no receiver,\nso `this` is the global object (sloppy) \u002F `undefined` (strict). An arrow callback\ninherits `this` from the surrounding scope.\n\n```js\nconst obj = {\n  value: 42,\n  start() {\n    setTimeout(function () { console.log(this.value) }, 100) \u002F\u002F undefined\u002Fglobal\n    setTimeout(() => console.log(this.value), 100)           \u002F\u002F 42 (arrow)\n  },\n}\n```\n\nThe arrow form (or `bind(this)`) is the standard way to keep the surrounding\nobject's `this` in timer callbacks.\n",{"id":275,"difficulty":34,"q":276,"a":277},"this-getter","What is this inside a getter or setter?","In a getter\u002Fsetter, `this` is the **object the property is accessed on** — just\nlike a regular method — so you can compute the value from other properties of that\nobject.\n\n```js\nconst person = {\n  first: 'Ada', last: 'Lovelace',\n  get fullName() { return `${this.first} ${this.last}` },\n  set fullName(v) { [this.first, this.last] = v.split(' ') },\n}\nperson.fullName        \u002F\u002F 'Ada Lovelace'\nperson.fullName = 'Grace Hopper'\n```\n\nDon't define a getter\u002Fsetter with an arrow — it wouldn't bind `this` to the\nobject. Use regular `get`\u002F`set` syntax.\n",{"id":279,"difficulty":34,"q":280,"a":281},"this-static","What is this inside a static method?","In a `static` method, `this` refers to the **class itself** (the constructor\nfunction), not an instance — so you can access other static members.\n\n```js\nclass MathUtil {\n  static PI = 3.14159\n  static circleArea(r) { return this.PI * r * r } \u002F\u002F this === MathUtil\n}\nMathUtil.circleArea(2) \u002F\u002F 12.566...\n```\n\nBecause `this` is the class, static methods can call sibling statics via `this`,\nand `this` even respects subclasses (if called as `SubClass.method()`, `this` is\n`SubClass`).\n",{"id":283,"difficulty":67,"q":284,"a":285},"self-pattern","What is the \"const self = this\" pattern?","Before arrow functions, you'd capture the outer `this` into an ordinary variable\n(`self`, `that`, or `_this`) so nested regular functions could reference it via\nthe closure, sidestepping their own `this`.\n\n```js\nfunction Timer() {\n  const self = this\n  this.seconds = 0\n  setInterval(function () {\n    self.seconds++ \u002F\u002F uses the captured outer `this`\n  }, 1000)\n}\n```\n\nArrow functions made this obsolete — `setInterval(() => this.seconds++, 1000)`\ndoes the same thing — but you'll still see `self`\u002F`that` in older codebases and\ntranspiled output.\n",{"id":287,"difficulty":34,"q":288,"a":289},"this-react-class","Why do React class components need to bind this?","A class method passed as an event handler (`onClick={this.handleClick}`) is\ndetached from the instance, so `this` is `undefined` when React calls it. Class\nbodies are strict, so you get a `TypeError` on `this.setState`.\n\n```js\nclass Btn extends React.Component {\n  constructor(p) { super(p); this.handleClick = this.handleClick.bind(this) }\n  handleClick() { this.setState(...) } \u002F\u002F needs bound `this`\n  \u002F\u002F or: handleClick = () => this.setState(...)  \u002F\u002F arrow class field\n}\n```\n\nFixes: bind in the constructor, or use an **arrow class field** (which captures\nthe instance `this`). Function components with hooks avoid the issue entirely.\n",{"id":291,"difficulty":34,"q":292,"a":293},"fluent-this","How does returning this enable method chaining?","If each method **returns `this`** (the instance), you can chain calls together —\nthe basis of fluent\u002Fbuilder APIs.\n\n```js\nclass Query {\n  parts = []\n  where(c) { this.parts.push(c); return this }\n  order(o) { this.parts.push(o); return this }\n  build() { return this.parts.join(' ') }\n}\nnew Query().where('a=1').order('b').build()\n```\n\nEach call resolves `this` to the same instance (implicit binding) and hands it\nback, so the next call operates on the same object. Returning `this` is the key.\n",{"id":295,"difficulty":50,"q":296,"a":297},"this-nested-regular","What is this in a regular function nested inside a method?","A regular function defined **inside** a method does **not** inherit the method's\n`this`. When called plainly, it gets its own default binding (`undefined`\u002Fglobal),\nwhich is a frequent bug.\n\n```js\nconst obj = {\n  items: [1, 2],\n  process() {\n    this.items.forEach(function (x) {\n      console.log(this.items) \u002F\u002F `this` is not obj here\n    })\n  },\n}\n```\n\nFixes: arrow function (inherits `this`), `thisArg`, or `const self = this`. The\nnested **regular** function losing `this` is the classic gotcha arrows solved.\n",{"id":299,"difficulty":34,"q":300,"a":301},"this-apply-spread","What is the difference between apply and the spread operator for arguments?","`apply` was historically used to pass an array of arguments **and** set `this`.\nThe **spread** operator (`...`) spreads an array into arguments without dealing\nwith `this`, so it's cleaner when you only need to forward arguments.\n\n```js\nconst nums = [5, 6, 2, 3]\nMath.max.apply(null, nums) \u002F\u002F 6 (old way — null thisArg)\nMath.max(...nums)          \u002F\u002F 6 (modern, no thisArg needed)\n```\n\nUse spread when `this` is irrelevant (most cases); keep `apply` when you must set\n`this` **and** pass an arguments array together.\n",{"id":303,"difficulty":34,"q":304,"a":305},"this-iife","What is this inside an IIFE?","An IIFE is invoked as a **plain function call**, so default binding applies:\n`this` is the **global object** in sloppy mode and **`undefined`** in strict mode.\n\n```js\n(function () {\n  console.log(this) \u002F\u002F window (sloppy) \u002F undefined (strict)\n})()\n\n(function () {\n  'use strict'\n  console.log(this) \u002F\u002F undefined\n})()\n```\n\nThat's why old module-pattern IIFEs sometimes passed `this`\u002F`window` in\nexplicitly: `(function (global) { ... })(this)`.\n",{"id":307,"difficulty":67,"q":308,"a":309},"this-object-literal","What is this in object method shorthand?","Method shorthand (`method() {}`) creates a regular function, so `this` is the\nobject the method is called on — standard implicit binding.\n\n```js\nconst calculator = {\n  value: 0,\n  add(n) { this.value += n; return this },\n}\ncalculator.add(5).add(3) \u002F\u002F this is calculator throughout -> value 8\n```\n\nShorthand is the right way to define methods that use `this`. (Contrast with an\narrow property, which would NOT bind to the object.)\n",{"id":311,"difficulty":50,"q":312,"a":313},"this-rebind-bound","Can you rebind an already-bound function?","No. Once a function is bound with `bind`, its `this` is **permanently fixed** —\ncalling `bind` again, or `call`\u002F`apply` with a different `this`, **cannot change**\nit.\n\n```js\nfunction f() { return this.id }\nconst bound = f.bind({ id: 1 })\nbound.call({ id: 2 }) \u002F\u002F 1 — the rebind is ignored\nbound.bind({ id: 3 })() \u002F\u002F 1 — still 1\n```\n\nThe first `bind` wins. This \"hard binding\" is sometimes the goal (locking `this`),\nbut it surprises people expecting `call` to override it.\n",{"id":315,"difficulty":50,"q":316,"a":317},"this-call-primitive","What happens when you pass a primitive as thisArg in sloppy mode?","In **sloppy mode**, a primitive `thisArg` passed to `call`\u002F`apply`\u002F`bind` is\n**boxed** into its wrapper object (`Number`, `String`, `Boolean`), and `null`\u002F\n`undefined` become the **global object**. In **strict mode**, `this` is left\nexactly as passed.\n\n```js\nfunction f() { return this }\n\u002F\u002F sloppy mode:\nf.call(5)         \u002F\u002F Number {5}  (boxed)\nf.call(null)      \u002F\u002F global object\n\u002F\u002F strict mode:\nf.call(5)         \u002F\u002F 5 (primitive, unboxed)\nf.call(null)      \u002F\u002F null\n```\n\nStrict mode's \"leave `this` as-is\" behavior is more predictable, another reason\nmodern code runs strict by default.\n",{"id":319,"difficulty":34,"q":320,"a":321},"arrow-no-arguments","Besides this, what else do arrow functions not have?","Arrow functions also lack their own **`arguments`** object, **`super`**, and\n**`new.target`**, and they **can't be used as constructors** (no `new`). Like\n`this`, `arguments` is inherited lexically from the enclosing function.\n\n```js\nfunction outer() {\n  const arrow = () => arguments[0] \u002F\u002F refers to outer's arguments\n  return arrow\n}\nouter(42)() \u002F\u002F 42\n\nconst Foo = () => {}\nnew Foo() \u002F\u002F TypeError: Foo is not a constructor\n```\n\nUse rest parameters (`...args`) instead of `arguments` in arrows. These omissions\nare why arrows are lightweight callbacks, not general-purpose functions.\n",{"id":323,"difficulty":34,"q":324,"a":325},"this-prototype","What is this in a prototype method?","A method on a constructor's `prototype` behaves like any method: when called as\n`instance.method()`, `this` is the **instance**. The method lives once on the\nprototype but `this` resolves per call to whichever instance invoked it.\n\n```js\nfunction User(name) { this.name = name }\nUser.prototype.greet = function () { return `Hi, ${this.name}` }\nconst u = new User('Ada')\nu.greet() \u002F\u002F 'Hi, Ada' — this === u\n```\n\nThis is how one shared prototype method serves all instances correctly — `this`\nis determined by the call site, not where the method is defined.\n",{"description":32},"JavaScript `this` interview questions — how this is bound, arrow vs regular functions, call\u002Fapply\u002Fbind and common context bugs.","javascript\u002Ffunctions\u002Fthis-keyword","The this Keyword","T0rjf5OhY_1gyL0HET2e_qhZvmR8BBTBn2VHHhuvRuI",{"id":332,"title":333,"body":334,"description":32,"difficulty":34,"extension":35,"framework":10,"frameworkSlug":8,"meta":338,"navigation":37,"order":339,"path":340,"questions":341,"related":178,"seo":465,"seoDescription":466,"stem":467,"subtopic":468,"topic":19,"topicSlug":21,"updated":469,"__hash__":470},"qa\u002Fjavascript\u002Ffunctions\u002Fhigher-order-functions.md","Higher Order Functions",{"type":29,"value":335,"toc":336},[],{"title":32,"searchDepth":20,"depth":20,"links":337},[],{},3,"\u002Fjavascript\u002Ffunctions\u002Fhigher-order-functions",[342,346,350,354,358,362,366,370,374,377,381,385,389,393,397,401,405,409,413,417,421,425,429,433,437,441,445,449,453,457,461],{"id":343,"difficulty":67,"q":344,"a":345},"what-is-hof","What is a higher-order function?","A **higher-order function (HOF)** is a function that does at least one of two\nthings: **takes one or more functions as arguments**, or **returns a\nfunction**. Any function that only deals with plain values is *first-order*.\n\n```js\n\u002F\u002F takes a function (callback)\n[1, 2, 3].map(n => n * 2)              \u002F\u002F map is a HOF\n\n\u002F\u002F returns a function\nconst multiplier = factor => n => n * factor  \u002F\u002F HOF returning a HOF\nconst double = multiplier(2)\ndouble(5) \u002F\u002F 10\n```\n\nHOFs are possible because functions in JavaScript are **first-class values** —\nthey can be stored, passed, and returned like any other value. They are the\nbackbone of functional-style JS and enable reuse without copy-pasting logic.\n",{"id":347,"difficulty":67,"q":348,"a":349},"what-is-callback","What is a callback function?","A **callback** is a function passed into another function so it can be\n**called back later** — either synchronously (now) or asynchronously (later).\n\n```js\n\u002F\u002F synchronous callback\n[1, 2, 3].forEach(n => console.log(n))   \u002F\u002F called once per element, now\n\n\u002F\u002F asynchronous callback\nsetTimeout(() => console.log('later'), 0) \u002F\u002F called after the timer fires\n```\n\nThe function receiving the callback decides **when** and **with what\narguments** to invoke it. A common gotcha: a synchronous-looking API may call\nthe callback asynchronously, so don't assume code after the call has the\ncallback's results yet.\n",{"id":351,"difficulty":67,"q":352,"a":353},"map-as-hof","How is Array.prototype.map a higher-order function?","`map` is a HOF because it **accepts a function** and applies it to every\nelement, returning a **new array** of the results. It abstracts the loop.\n\n```js\nconst nums = [1, 2, 3]\nconst squared = nums.map(n => n * n)   \u002F\u002F [1, 4, 9]\n\u002F\u002F nums is unchanged — map does not mutate\n```\n\nThe callback receives `(element, index, array)`. **Pitfall:** `map` is for\ntransforming into a new array — if you only need side effects (logging,\npushing to the DOM) use `forEach` instead, otherwise you allocate an array of\n`undefined` you never use.\n",{"id":355,"difficulty":67,"q":356,"a":357},"filter-as-hof","What does Array.prototype.filter do and why is it a HOF?","`filter` is a HOF that takes a **predicate** (a function returning a boolean)\nand returns a **new array** containing only the elements for which the\npredicate is truthy.\n\n```js\nconst nums = [1, 2, 3, 4]\nconst evens = nums.filter(n => n % 2 === 0)  \u002F\u002F [2, 4]\n```\n\nThe result's **truthiness** is what matters, not strict `true`. **Pitfall:**\nreturning a non-boolean accidentally — e.g. `filter(n => n.id)` keeps elements\nwith truthy `id`, which silently drops items whose id is `0` or `''`.\n",{"id":359,"difficulty":34,"q":360,"a":361},"reduce-as-hof","Explain reduce as a higher-order function.","`reduce` is the most general array HOF: it takes a **reducer function**\n`(accumulator, element) => newAccumulator` plus an initial value, and folds\nthe whole array down to a **single value** (which can itself be an array or\nobject).\n\n```js\nconst sum = [1, 2, 3, 4].reduce((acc, n) => acc + n, 0)  \u002F\u002F 10\n\n\u002F\u002F map and filter can both be expressed via reduce\nconst doubled = [1, 2, 3].reduce((acc, n) => [...acc, n * 2], []) \u002F\u002F [2,4,6]\n```\n\n**Pitfall:** omitting the initial value. Without it, the first element becomes\nthe accumulator and iteration starts at index 1 — and `reduce` on an **empty\narray with no initial value throws** a TypeError.\n",{"id":363,"difficulty":34,"q":364,"a":365},"pure-vs-callback","Why do HOFs like map\u002Ffilter\u002Freduce make code more reusable?","They **separate the iteration mechanism from the per-element logic**. The HOF\nowns the loop, bounds checking, and array allocation; you supply only the\nsmall piece that varies. This is the **template method** idea expressed with\nfunctions.\n\n```js\n\u002F\u002F imperative: loop boilerplate repeated everywhere\nconst out = []\nfor (let i = 0; i \u003C users.length; i++) out.push(users[i].name)\n\n\u002F\u002F declarative: intent is obvious, no boilerplate\nconst names = users.map(u => u.name)   \u002F\u002F\n```\n\nBecause the callback is just a value, you can name it, test it in isolation,\nand reuse it across many call sites — reducing duplication and bugs.\n",{"id":367,"difficulty":34,"q":368,"a":369},"function-composition","What is function composition?","**Composition** combines small functions into a bigger one, where the output\nof each becomes the input of the next — `compose(f, g)(x) === f(g(x))`.\n\n```js\nconst compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x)\nconst pipe    = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x)\n\nconst clean = pipe(s => s.trim(), s => s.toLowerCase())\nclean('  HELLO ')  \u002F\u002F 'hello'   reads left-to-right\n```\n\n`compose` runs **right-to-left** (math convention); `pipe` runs\n**left-to-right** (reads like a pipeline). **Pitfall:** each function should\ntake and return a single value — composition breaks down with multi-arg\nfunctions unless you curry them first.\n",{"id":371,"difficulty":34,"q":372,"a":373},"what-is-currying","What is currying?","**Currying** transforms a function of N arguments into N nested functions that\neach take **one argument** and return the next function until all args are\ncollected.\n\n```js\nconst add = a => b => c => a + b + c   \u002F\u002F curried\nadd(1)(2)(3)   \u002F\u002F 6\n\n\u002F\u002F vs the normal form\nconst addN = (a, b, c) => a + b + c\naddN(1, 2, 3)  \u002F\u002F 6\n```\n\nCurrying enables **partial application** and clean composition, because each\nstage returns a specialized function. **Pitfall:** deeply curried APIs hurt\nreadability and are harder to debug — reserve currying for cases where the\npartial-application benefit is real.\n",{"id":95,"difficulty":34,"q":375,"a":376},"What is partial application and how does it differ from currying?","**Partial application** fixes *some* of a function's arguments now, producing a\nnew function that takes the *rest* later. **Currying** is stricter: it always\nbreaks a function into a chain of **one-argument** functions.\n\n```js\nconst greet = (greeting, name) => `${greeting}, ${name}!`\nconst hi = greet.bind(null, 'Hi')   \u002F\u002F partial application via bind\nhi('Sam')  \u002F\u002F 'Hi, Sam!'   greeting already fixed\n```\n\nSo every curried call is a partial application, but partial application can\nfix several arguments at once and isn't restricted to one-at-a-time. `bind` is\nthe built-in tool for it (ignoring the `this` argument here with `null`).\n",{"id":378,"difficulty":50,"q":379,"a":380},"point-free-style","What is point-free (tacit) style?","**Point-free style** defines functions **without naming their arguments**,\nbuilding them by composing other functions instead. The \"point\" is the data\nargument you don't mention.\n\n```js\n\u002F\u002F pointed\nconst isOdd = n => n % 2 === 1\nconst countOdds = arr => arr.filter(isOdd).length\n\n\u002F\u002F point-free helper composed from smaller pieces\nconst prop = key => obj => obj[key]\nconst names = users.map(prop('name'))   \u002F\u002F no obj parameter named\n```\n\nIt can read very cleanly, but **pitfall:** taken too far it becomes cryptic\nand stack traces lose meaningful names. Use it where it genuinely clarifies.\n",{"id":382,"difficulty":34,"q":383,"a":384},"what-is-memoization","What is memoization and how do you implement it with a HOF?","**Memoization** caches a pure function's results keyed by its arguments, so\nrepeated calls with the same input return instantly instead of recomputing.\nA HOF wraps the original function and keeps the cache in a **closure**.\n\n```js\nfunction memoize(fn) {\n  const cache = new Map()\n  return function (arg) {\n    if (cache.has(arg)) return cache.get(arg)   \u002F\u002F cache hit\n    const result = fn.call(this, arg)\n    cache.set(arg, result)\n    return result\n  }\n}\n```\n\n**Pitfall:** it only works for **pure** functions (same input -> same output)\nand the naive version keys on a single primitive arg — multi-arg or object\nkeys need a serialization strategy and risk unbounded memory growth.\n",{"id":386,"difficulty":34,"q":387,"a":388},"debounce-as-hof","How would you implement debounce, and why is it a HOF?","**Debounce** returns a wrapped function that delays calling the original until\nactivity has **stopped for a quiet period**; each new call resets the timer.\nIt's a HOF: it takes a function and returns a closure holding the timer.\n\n```js\nfunction debounce(fn, wait) {\n  let timer\n  return function (...args) {\n    clearTimeout(timer)\n    timer = setTimeout(() => fn.apply(this, args), wait)   \u002F\u002F resets\n  }\n}\nconst onSearch = debounce(query => fetchResults(query), 300)\n```\n\nGreat for search-as-you-type or resize handlers. **Pitfall:** the wrapper must\nforward `this` and `args` with `apply`, or the debounced handler loses its\ncontext and the event arguments.\n",{"id":390,"difficulty":34,"q":391,"a":392},"throttle-as-hof","What is throttle and how does it differ from debounce?","**Throttle** guarantees the function runs **at most once per interval**, no\nmatter how often it's called — useful for scroll or mousemove. **Debounce**\ninstead waits until calls *stop*. Both are HOFs returning a stateful closure.\n\n```js\nfunction throttle(fn, interval) {\n  let last = 0\n  return function (...args) {\n    const now = Date.now()\n    if (now - last >= interval) {        \u002F\u002F fire on leading edge\n      last = now\n      fn.apply(this, args)\n    }\n  }\n}\n```\n\n**Rule of thumb:** throttle for *steady sampling* during continuous events;\ndebounce for *\"do it once they're done\"* events.\n",{"id":394,"difficulty":34,"q":395,"a":396},"once-hof","How do you implement a once() higher-order function?","`once` returns a wrapper that lets the underlying function run **only the\nfirst time**; later calls return the cached first result and skip execution.\nThe \"have I run yet\" flag and result live in a closure.\n\n```js\nfunction once(fn) {\n  let called = false, result\n  return function (...args) {\n    if (!called) {\n      called = true\n      result = fn.apply(this, args)   \u002F\u002F runs exactly once\n    }\n    return result\n  }\n}\nconst init = once(() => console.log('setup'))\ninit(); init()   \u002F\u002F logs 'setup' only once\n```\n\nHandy for idempotent initialization. **Pitfall:** the result is cached forever\n— if the first call threw, decide whether `called` should stay false to allow\na retry.\n",{"id":398,"difficulty":34,"q":399,"a":400},"returning-functions","Why would a function return another function?","Returning a function lets you **pre-configure behavior now and defer\nexecution to later**, capturing the configuration in a closure. This is the\nmechanism behind factories, currying, and middleware.\n\n```js\nfunction makeTagger(tag) {\n  return content => `\u003C${tag}>${content}\u003C\u002F${tag}>`   \u002F\u002F remembers `tag`\n}\nconst h1 = makeTagger('h1')\nh1('Hello')   \u002F\u002F '\u003Ch1>Hello\u003C\u002Fh1>'   tag captured\n```\n\nThe returned function is **specialized** without you rewriting it. The key\nenabler is the closure: each returned function keeps its own copy of the\ncaptured configuration.\n",{"id":402,"difficulty":34,"q":403,"a":404},"callbacks-sync-async","What's the difference between synchronous and asynchronous callbacks?","A **synchronous callback** runs to completion *before* the HOF returns (like\n`map`'s callback). An **asynchronous callback** is scheduled and runs *later*,\nafter the current call stack clears (like `setTimeout` or a fetch handler).\n\n```js\nconsole.log('A')\n[1].forEach(() => console.log('B'))     \u002F\u002F sync -> B before C\nsetTimeout(() => console.log('D'), 0)   \u002F\u002F async -> D last\nconsole.log('C')\n\u002F\u002F order: A, B, C, D\n```\n\n**Pitfall:** mixing them in one API (\"sometimes sync, sometimes async\") causes\nsubtle bugs — choose one contract. This is also why callback-based async code\nled to \"callback hell\" and motivated Promises.\n",{"id":406,"difficulty":50,"q":407,"a":408},"map-parseint-gotcha","Why does ['1','2','3'].map(parseInt) not return [1, 2, 3]?","`map` calls the callback with **three** arguments — `(value, index, array)` —\nbut `parseInt(string, radix)` reads the **second** as a radix. So you actually\ncall `parseInt('1', 0)`, `parseInt('2', 1)`, `parseInt('3', 2)`.\n\n```js\n['1', '2', '3'].map(parseInt)\n\u002F\u002F parseInt('1', 0) -> 1   (radix 0 ignored -> base 10)\n\u002F\u002F parseInt('2', 1) -> NaN (radix 1 invalid)\n\u002F\u002F parseInt('3', 2) -> NaN ('3' not a binary digit)\n\u002F\u002F result: [1, NaN, NaN]\n```\n\n**Fix:** wrap it so only the value is passed:\n`['1','2','3'].map(s => parseInt(s, 10))` -> `[1, 2, 3]`. The lesson: be\ncareful passing a multi-arity built-in directly as a callback.\n",{"id":410,"difficulty":50,"q":411,"a":412},"losing-this-method-ref","Why does passing a method reference as a callback often lose `this`?","Passing `obj.method` extracts the **function value alone** — the `obj`\nreceiver is *not* attached. When the HOF later calls it as a plain function,\n`this` is `undefined` (strict) or the global object.\n\n```js\nconst counter = {\n  count: 0,\n  inc() { this.count++ }\n}\n[1, 2].forEach(counter.inc)   \u002F\u002F `this` is not `counter`\n```\n\n**Fixes:** bind it — `forEach(counter.inc.bind(counter))` — or wrap in an\narrow that preserves the receiver — `forEach(() => counter.inc())`. The\nroot cause is that `this` is determined by **how** a function is called, not\nwhere it was defined.\n",{"id":414,"difficulty":34,"q":415,"a":416},"composition-vs-chaining","How does method chaining relate to function composition?","**Method chaining** (`arr.filter(...).map(...).reduce(...)`) is composition\nwhere each step is a **method returning a chainable value**. Standalone\n**composition** (`pipe(f, g, h)`) works on free functions and any data type,\nnot just arrays.\n\n```js\n\u002F\u002F chaining\nconst total = orders.filter(o => o.paid).map(o => o.amount)\n                    .reduce((a, b) => a + b, 0)   \u002F\u002F reads top-to-bottom\n\n\u002F\u002F composition with free functions\nconst total2 = pipe(\n  os => os.filter(o => o.paid),\n  os => os.map(o => o.amount),\n  os => os.reduce((a, b) => a + b, 0)\n)(orders)\n```\n\nChaining is ergonomic when the methods exist; composition is more general and\ndecouples logic from the data's prototype. **Pitfall:** long chains over large\narrays create many intermediate arrays.\n",{"id":418,"difficulty":34,"q":419,"a":420},"flatmap-hof","What does flatMap do and when is it useful?","`flatMap` is a HOF that **maps then flattens one level** in a single pass. It's\nequivalent to `arr.map(fn).flat()` but more efficient and expressive.\n\n```js\nconst sentences = ['hello world', 'foo bar']\nconst words = sentences.flatMap(s => s.split(' '))\n\u002F\u002F ['hello', 'world', 'foo', 'bar']   flattened\n\n\u002F\u002F also handy to map-and-filter: return [] to drop\n[1, 2, 3].flatMap(n => n % 2 ? [n] : [])  \u002F\u002F [1, 3]\n```\n\n**Pitfall:** it only flattens **one** level — deeply nested results need\n`flat(Infinity)` afterwards.\n",{"id":422,"difficulty":67,"q":423,"a":424},"every-some-hof","How do every() and some() use callbacks?","Both are HOFs taking a **predicate**. `every` returns `true` only if the\npredicate passes for **all** elements; `some` returns `true` if **at least\none** passes. Both **short-circuit**.\n\n```js\n[2, 4, 6].every(n => n % 2 === 0)  \u002F\u002F true\n[1, 2, 3].some(n => n > 2)         \u002F\u002F true (stops at 3)\n```\n\n`every` stops at the first falsy result; `some` stops at the first truthy\nresult. **Edge case:** `[].every(...)` is `true` (vacuous truth) and\n`[].some(...)` is `false`.\n",{"id":426,"difficulty":50,"q":427,"a":428},"bind-vs-arrow-callback","When wiring a callback, should you use bind or an arrow wrapper?","Both fix the receiver. `bind` creates a **new bound function once**, ideal when\nyou need a **stable reference** (e.g. to later `removeEventListener`). An arrow\nwrapper is created fresh each render\u002Fcall and is convenient for forwarding\nchanging arguments.\n\n```js\n\u002F\u002F stable, removable\nconst handler = this.onClick.bind(this)\nel.addEventListener('click', handler)\nel.removeEventListener('click', handler)   \u002F\u002F same reference\n\n\u002F\u002F arrow re-created each time -> cannot remove\nel.addEventListener('click', () => this.onClick())  \u002F\u002F no handle to remove\n```\n\n**Pitfall:** binding inside JSX\u002Frender or in a loop creates a new function\nevery time, which can defeat memoization and break listener removal.\n",{"id":430,"difficulty":34,"q":431,"a":432},"identity-and-constant","What are identity and constant functions and why are they useful in HOF code?","`identity = x => x` returns its argument unchanged; `constant = x => () => x`\nreturns a function that always yields `x`. They are tiny **building blocks**\nthat make HOF pipelines uniform.\n\n```js\nconst identity = x => x\n\u002F\u002F filter out falsy values with no custom predicate\n['a', '', 'b', null].filter(identity)   \u002F\u002F ['a', 'b']\n\nconst always5 = (() => () => 5)()\n[1, 2, 3].map(always5)   \u002F\u002F [5, 5, 5]\n```\n\nThey shine as **default callbacks** (e.g. a sort key defaulting to identity)\nand in composition where you need a no-op transform.\n",{"id":434,"difficulty":50,"q":435,"a":436},"compose-data-last","Why do functional libraries favor \"data-last\" argument order?","**Data-last** means the data parameter comes *last*, so the earlier\nconfiguration args can be **partially applied** to build reusable, composable\nfunctions. The data flows in only at the end of a pipeline.\n\n```js\nconst map = fn => arr => arr.map(fn)        \u002F\u002F data (arr) last\nconst filter = pred => arr => arr.filter(pred)\n\nconst process = pipe(filter(x => x > 0), map(x => x * 2))\nprocess([-1, 2, 3])   \u002F\u002F [4, 6]   data supplied last\n```\n\nNative array methods are **data-first** (`arr.map(fn)`), which is why you\noften wrap them. The trade-off: data-last composes beautifully but reads\nbackwards from the method style most JS developers know.\n",{"id":438,"difficulty":34,"q":439,"a":440},"callback-error-handling","What is the \"error-first\" callback convention?","The Node-style **error-first callback** convention passes the error as the\n**first argument** and the result(s) afterward: `callback(err, data)`. If\n`err` is truthy, something failed.\n\n```js\nfs.readFile('x.txt', (err, data) => {\n  if (err) return handle(err)   \u002F\u002F check error first\n  use(data)\n})\n```\n\n**Pitfall:** forgetting to `return` after handling the error lets the success\npath run with `undefined` data. This convention predates Promises, which\nlargely replaced it with `.then\u002F.catch` and `async\u002Fawait`.\n",{"id":442,"difficulty":34,"q":443,"a":444},"hof-this-arg","How do you set `this` for an array HOF callback without binding?","Many array HOFs accept an optional **`thisArg`** as their last parameter. When\nprovided (and the callback is a regular function, not an arrow), `this` inside\nthe callback is set to it.\n\n```js\nconst ctx = { factor: 3 }\n[1, 2, 3].map(function (n) { return n * this.factor }, ctx)  \u002F\u002F [3, 6, 9]\n```\n\n**Pitfall:** `thisArg` is **ignored by arrow callbacks**, because arrows take\n`this` lexically. Most modern code just uses an arrow that closes over the\nvalue instead of relying on `thisArg`.\n",{"id":446,"difficulty":50,"q":447,"a":448},"composing-async","How do you compose asynchronous functions?","Plain `compose`\u002F`pipe` assume synchronous functions. For async, each step\nreturns a Promise, so you **await between stages** — often by reducing over an\ninitial resolved Promise.\n\n```js\nconst pipeAsync = (...fns) => x =>\n  fns.reduce((acc, fn) => acc.then(fn), Promise.resolve(x))\n\nconst run = pipeAsync(fetchUser, u => fetchPosts(u.id), posts => posts.length)\nrun(42).then(console.log)   \u002F\u002F each step awaits the previous\n```\n\n**Pitfall:** mixing sync and async functions in one pipe is fine here because\n`then` auto-wraps non-Promise returns — but an unhandled rejection in any\nstage rejects the whole chain, so attach a `.catch`.\n",{"id":450,"difficulty":50,"q":451,"a":452},"curry-auto","How would you write a generic curry() helper?","A generic `curry` collects arguments until it has received as many as the\nfunction's **declared arity** (`fn.length`), then invokes it. Until then it\nreturns a function that accumulates more args.\n\n```js\nfunction curry(fn) {\n  return function curried(...args) {\n    if (args.length >= fn.length) return fn.apply(this, args)\n    return (...next) => curried.apply(this, [...args, ...next])   \u002F\u002F\n  }\n}\nconst add = curry((a, b, c) => a + b + c)\nadd(1)(2)(3)   \u002F\u002F 6\nadd(1, 2)(3)   \u002F\u002F 6   — flexible grouping\n```\n\n**Pitfall:** it relies on `fn.length`, which **excludes** rest params and\nparameters with defaults — so currying variadic functions doesn't work without\npassing an explicit arity.\n",{"id":454,"difficulty":50,"q":455,"a":456},"hof-reuse-vs-inheritance","How do HOFs offer an alternative to class inheritance for sharing behavior?","Instead of subclassing to share behavior, you can **wrap functions with HOFs**\n(decorators) to add cross-cutting concerns like logging, caching, or retries —\n**composition over inheritance**.\n\n```js\nconst withLogging = fn => (...args) => {\n  console.log('call', fn.name, args)\n  return fn(...args)\n}\nconst withRetry = fn => async (...args) => {\n  try { return await fn(...args) } catch { return fn(...args) }\n}\nconst robustFetch = withLogging(withRetry(fetchData))   \u002F\u002F stacked\n```\n\nEach concern is an independent, testable HOF you can stack in any order. This\navoids deep inheritance hierarchies and the fragile base-class problem.\n",{"id":458,"difficulty":34,"q":459,"a":460},"tap-debugging","What is a tap() function and how does it help debug pipelines?","`tap` runs a **side effect** (like logging) on a value and then **returns the\nvalue unchanged**, so you can drop it into a composition without altering the\ndata flow.\n\n```js\nconst tap = fn => x => { fn(x); return x }\n\nconst result = pipe(\n  x => x + 1,\n  tap(x => console.log('after +1:', x)),   \u002F\u002F peeks, passes through\n  x => x * 2\n)(5)   \u002F\u002F logs 6, result 12\n```\n\nIt's the functional equivalent of a breakpoint. **Pitfall:** because it's for\nside effects, don't accidentally `return fn(x)` — that would replace the value\nand corrupt the pipeline.\n",{"id":462,"difficulty":50,"q":463,"a":464},"avoid-shared-mutable-closure","What bug can a HOF cause by sharing mutable state across returned functions?","If a HOF closes over a **shared mutable variable** and returns functions that\nall reference it, they can interfere with each other — the classic loop-closure\ntrap.\n\n```js\nfunction makeHandlers() {\n  const fns = []\n  for (var i = 0; i \u003C 3; i++) fns.push(() => i)   \u002F\u002F all see final i\n  return fns\n}\nmakeHandlers().map(f => f())   \u002F\u002F [3, 3, 3]\n```\n\n**Fix:** use `let` (per-iteration binding) so each closure captures its own\n`i` -> `[0, 1, 2]`. The deeper lesson: when a HOF returns multiple closures,\nbe deliberate about whether they should **share** or **own** their captured\nstate.\n",{"description":32},"JavaScript higher-order function interview questions — callbacks, map\u002Ffilter\u002F reduce, composition, currying, partial application, memoization, debounce and throttle, plus classic callback pitfalls.","javascript\u002Ffunctions\u002Fhigher-order-functions","Higher-Order Functions","2026-06-18","gajpsA9HuJ91gZ5frBbNlC6sHDnB7KjdH7Q19PqI4FY",{"id":472,"title":473,"body":474,"description":32,"difficulty":34,"extension":35,"framework":10,"frameworkSlug":8,"meta":478,"navigation":37,"order":479,"path":480,"questions":481,"related":178,"seo":602,"seoDescription":603,"stem":604,"subtopic":605,"topic":19,"topicSlug":21,"updated":469,"__hash__":606},"qa\u002Fjavascript\u002Ffunctions\u002Ffunction-types-parameters.md","Function Types Parameters",{"type":29,"value":475,"toc":476},[],{"title":32,"searchDepth":20,"depth":20,"links":477},[],{},4,"\u002Fjavascript\u002Ffunctions\u002Ffunction-types-parameters",[482,486,490,494,498,502,506,510,514,518,522,526,530,534,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598],{"id":483,"difficulty":67,"q":484,"a":485},"declaration-vs-expression","What is the difference between a function declaration and a function expression?","A **function declaration** stands alone as a statement and is **hoisted**\nwhole, so you can call it before its line. A **function expression** assigns a\nfunction to a variable; only the variable is hoisted, not its value.\n\n```js\nsayHi()                       \u002F\u002F works — declaration hoisted\nfunction sayHi() {}\n\nsayBye()                      \u002F\u002F TypeError: sayBye is not a function\nvar sayBye = function () {}   \u002F\u002F expression — value assigned at runtime\n```\n\n**Pitfall:** with `let`\u002F`const` the expression variable is in the temporal\ndead zone, so calling early throws a ReferenceError instead. Choose\ndeclarations for top-level reusable functions and expressions when passing a\nfunction as a value.\n",{"id":487,"difficulty":67,"q":488,"a":489},"named-vs-anonymous","What is the difference between named and anonymous functions?","A **named function** has its own identifier; an **anonymous function** has\nnone. The name aids **recursion** and **stack traces**.\n\n```js\nconst fac = function factorial(n) {           \u002F\u002F named function expression\n  return n \u003C= 1 ? 1 : n * factorial(n - 1)    \u002F\u002F can call itself by name\n}\n\n[1].map(function () {})    \u002F\u002F anonymous — appears unnamed in traces\n```\n\nModern engines infer a name for anonymous functions assigned to a variable, so\n`const f = () => {}` has `f.name === 'f'`. **Pitfall:** a named function\nexpression's inner name is only visible **inside** the function, not outside.\n",{"id":491,"difficulty":34,"q":492,"a":493},"arrow-vs-regular","How do arrow functions differ from regular functions?","Arrow functions are more than shorter syntax. They have **no own `this`,\n`arguments`, `super`, or `new.target`** — they inherit `this` lexically — and\nthey **cannot be used as constructors**.\n\n```js\nconst obj = {\n  items: [1, 2],\n  log() {\n    this.items.forEach(i => console.log(this.items))  \u002F\u002F `this` is obj\n  }\n}\nconst Arrow = () => {}\nnew Arrow()   \u002F\u002F TypeError: Arrow is not a constructor\n```\n\n**Pitfall:** don't use an arrow as an object **method** if you need `this` to\nbe the object — it will be the surrounding scope's `this` (often the module or\nwindow), not the object.\n",{"id":495,"difficulty":34,"q":496,"a":497},"what-is-iife","What is an IIFE and why use one?","An **IIFE (Immediately Invoked Function Expression)** is a function defined and\ncalled at once. It creates a **private scope** so its variables don't leak.\n\n```js\n(function () {\n  const secret = 42        \u002F\u002F not visible outside\n  console.log(secret)\n})()                       \u002F\u002F runs immediately\n\n\u002F\u002F arrow form\n(() => { \u002F* ... *\u002F })()\n```\n\nThe wrapping parens turn the declaration into an **expression** so it can be\ninvoked. IIFEs powered the old **module pattern** before ES modules. **Pitfall:**\na missing semicolon before an IIFE can make the previous line try to call it —\ndefensively prefix with `;`.\n",{"id":499,"difficulty":67,"q":500,"a":501},"first-class-functions","What does it mean that functions are first-class in JavaScript?","**First-class** means functions are treated like any other **value**: they can\nbe assigned to variables, stored in arrays\u002Fobjects, passed as arguments, and\nreturned from functions.\n\n```js\nconst ops = { add: (a, b) => a + b }   \u002F\u002F stored in an object\nconst fns = [Math.abs, Math.sqrt]      \u002F\u002F stored in an array\nconst run = fn => fn(16)               \u002F\u002F passed as argument\nrun(fns[1])   \u002F\u002F 4\n```\n\nThis is the foundation that makes **higher-order functions, callbacks, and\nclosures** possible. Without first-class functions, none of the functional\npatterns in JS would work.\n",{"id":503,"difficulty":67,"q":504,"a":505},"default-parameters","How do default parameters work?","A **default parameter** supplies a value when the argument is **`undefined`**\n(either omitted or explicitly `undefined`). The default expression is\nevaluated **at call time**, only when needed.\n\n```js\nfunction greet(name = 'friend') { return `Hi, ${name}` }\ngreet()           \u002F\u002F 'Hi, friend'\ngreet(undefined)  \u002F\u002F 'Hi, friend'   — default applies\ngreet(null)       \u002F\u002F 'Hi, null'     null is NOT undefined\n```\n\n**Pitfall:** only `undefined` triggers the default — passing `null`, `0`, or\n`''` does not. Defaults can also reference **earlier parameters**:\n`(a, b = a * 2) => ...`.\n",{"id":507,"difficulty":50,"q":508,"a":509},"defaults-evaluation-order","When are default parameter expressions evaluated, and in what order?","Defaults are evaluated **left to right at call time**, each in a scope where\n**earlier parameters are already bound** but later ones are not. They are fresh\nevery call, not cached.\n\n```js\nlet calls = 0\nconst next = () => ++calls\nfunction f(a = next(), b = a + 1) { return [a, b] }\nf()      \u002F\u002F [1, 2]   — next() ran once, b saw a\nf(10)    \u002F\u002F [10, 11] — default for a skipped, next() not called\n```\n\n**Pitfall:** referencing a **later** parameter in an earlier default throws a\nReferenceError (TDZ): `function g(a = b, b = 1) {}` — `g()`. Also, an object\ndefault like `{ items: [] }` creates a **new array each call**, avoiding the\nshared-mutable-default trap seen in some other languages.\n",{"id":511,"difficulty":34,"q":512,"a":513},"rest-parameters","What are rest parameters?","A **rest parameter** (`...args`) collects all remaining arguments into a\n**real array**. It must be the **last** parameter and there can be only one.\n\n```js\nfunction sum(...nums) {\n  return nums.reduce((a, b) => a + b, 0)   \u002F\u002F nums is a true array\n}\nsum(1, 2, 3)   \u002F\u002F 6\n\nfunction tagged(first, ...rest) { \u002F* first separate, rest gathers the tail *\u002F }\n```\n\nUnlike the old `arguments` object, rest params are a genuine `Array` (with\n`map`, `filter`, etc.). **Pitfall:** rest params are **excluded** from\n`fn.length` (arity).\n",{"id":515,"difficulty":34,"q":516,"a":517},"arguments-object","What is the arguments object?","`arguments` is an **array-like** object available inside **regular** (non-arrow)\nfunctions, holding **all** passed arguments regardless of declared parameters.\n\n```js\nfunction f() {\n  return arguments.length          \u002F\u002F works even with no named params\n}\nf(1, 2, 3)   \u002F\u002F 3\n\n\u002F\u002F it's array-LIKE, not an array\nArray.prototype.slice.call(arguments)   \u002F\u002F convert to real array\n[...arguments]                          \u002F\u002F modern conversion\n```\n\n**Pitfall:** it lacks array methods (`map`, `forEach`), so convert it first.\nIn modern code, prefer **rest parameters** over `arguments`.\n",{"id":519,"difficulty":34,"q":520,"a":521},"why-arrows-no-arguments","Why don't arrow functions have their own arguments object?","Arrow functions deliberately have **no own `arguments`** — like `this`, they\ninherit it lexically from the enclosing **regular** function (or it's\nundefined at module top level).\n\n```js\nfunction outer() {\n  const inner = () => arguments[0]   \u002F\u002F refers to outer's arguments\n  return inner()\n}\nouter('hi')   \u002F\u002F 'hi'\n\nconst f = () => arguments   \u002F\u002F ReferenceError at top level\n```\n\nThe fix when you need all args in an arrow is **rest parameters**:\n`const f = (...args) => args`. This lexical behavior is exactly why arrows are\ngreat as callbacks but unsuitable as methods needing their own `arguments`.\n",{"id":523,"difficulty":34,"q":524,"a":525},"function-length","What does a function's length property return?","`fn.length` is the function's **arity** — the number of parameters **before**\nthe first one with a default value or a rest parameter. It does **not** count\nthose.\n\n```js\n((a, b) => {}).length        \u002F\u002F 2\n((a, b = 1) => {}).length    \u002F\u002F 1   — stops at first default\n((a, ...rest) => {}).length  \u002F\u002F 1   — rest excluded\n((a, b, c = 1, d) => {}).length \u002F\u002F 2 — counts up to first default\n```\n\n**Pitfall:** because defaults and rest reduce `length`, generic helpers like\n`curry` that rely on `fn.length` misbehave on such functions. `length` is\nread-only.\n",{"id":527,"difficulty":67,"q":528,"a":529},"function-name","How is a function's name property determined?","`fn.name` is the function's name string, used in **stack traces** and\ndebugging. Engines **infer** it from the variable or property a function is\nassigned to when the function itself is anonymous.\n\n```js\nfunction foo() {}\nfoo.name                 \u002F\u002F 'foo'\nconst bar = () => {}\nbar.name                 \u002F\u002F 'bar'    — inferred\nconst o = { baz() {} }\no.baz.name               \u002F\u002F 'baz'\n[].map(() => {}).name    \u002F\u002F '' or anonymous — not assigned to a binding\n```\n\n`bind` prepends `'bound '`: `foo.bind(null).name === 'bound foo'`. **Pitfall:**\nminifiers rename functions, so don't rely on `name` for program logic.\n",{"id":531,"difficulty":34,"q":532,"a":533},"parameter-destructuring","How does parameter destructuring work?","You can **destructure** an object or array argument right in the parameter\nlist, pulling out the fields you need and optionally giving them defaults.\n\n```js\nfunction createUser({ name, role = 'user', age } = {}) {\n  return `${name} (${role})`\n}\ncreateUser({ name: 'Ada', role: 'admin' })   \u002F\u002F 'Ada (admin)'\ncreateUser()                                  \u002F\u002F 'undefined (user)' no crash\n```\n\nThe trailing `= {}` is crucial: it lets the function be **called with no\nargument** without throwing. **Pitfall:** omitting it and calling\n`createUser()` throws \"Cannot destructure property of undefined\".\n",{"id":535,"difficulty":67,"q":536,"a":537},"methods-vs-functions","What is the difference between a method and a function?","A **method** is simply a function stored as an **object property** and usually\ncalled with a receiver (`obj.method()`), so its `this` is that object. A plain\n**function** is called standalone and its `this` depends on call context.\n\n```js\nconst calc = {\n  value: 10,\n  double() { return this.value * 2 }   \u002F\u002F method — `this` is calc\n}\ncalc.double()   \u002F\u002F 20\n\nconst d = calc.double\nd()             \u002F\u002F `this` is undefined — now a detached function call\n```\n\n**Pitfall:** detaching a method (`const d = calc.double`) loses the receiver;\n`this` is determined by **how** it's called, not where it lives.\n",{"id":539,"difficulty":34,"q":540,"a":541},"shorthand-method","What is method shorthand and how does it differ from a property holding a function?","**Method shorthand** (`foo() {}` inside an object) is mostly equivalent to\n`foo: function () {}`, but shorthand methods can use **`super`** and are\ncreated as **non-constructable** (you can't `new` them).\n\n```js\nconst obj = {\n  greet() { return 'hi' },             \u002F\u002F shorthand\n  greet2: function () { return 'hi' }  \u002F\u002F property with function\n}\nnew obj.greet2()   \u002F\u002F works (legacy)\nnew obj.greet()    \u002F\u002F TypeError: not a constructor\n```\n\n**Pitfall:** the inability to construct shorthand methods is by design; it's\nrarely an issue but surprising if you relied on it.\n",{"id":543,"difficulty":34,"q":544,"a":545},"recursion-basics","What is recursion and what does every recursive function need?","**Recursion** is a function calling **itself** to solve a smaller version of a\nproblem. Every recursive function needs a **base case** that stops the\nrecursion and a **recursive case** that moves toward it.\n\n```js\nfunction factorial(n) {\n  if (n \u003C= 1) return 1          \u002F\u002F base case\n  return n * factorial(n - 1)   \u002F\u002F recursive case, n shrinks\n}\nfactorial(5)   \u002F\u002F 120\n```\n\n**Pitfall:** a missing or unreachable base case causes infinite recursion and\na **\"Maximum call stack size exceeded\"** error. Deep recursion can also blow\nthe stack even when correct.\n",{"id":547,"difficulty":50,"q":548,"a":549},"tail-call","What is a tail call, and does JavaScript optimize them?","A **tail call** is when a function's **last action** is to return the result of\nanother call, with nothing left to do afterward. Proper Tail Calls (PTC) would\nlet the engine **reuse the stack frame**, enabling unbounded recursion.\n\n```js\nfunction fact(n, acc = 1) {\n  if (n \u003C= 1) return acc\n  return fact(n - 1, n * acc)   \u002F\u002F tail position — no pending multiply\n}\n```\n\n**Reality:** although PTC is in the ES2015 spec, **only Safari\u002FJavaScriptCore**\nimplements it; V8 (Chrome\u002FNode) and Firefox do not. **Pitfall:** so don't rely\non tail-call elimination for deep recursion — use a loop or an explicit stack\ninstead.\n",{"id":551,"difficulty":67,"q":552,"a":553},"arity-definition","What is arity?","**Arity** is the **number of arguments a function expects** — its declared\nparameter count, reflected (with caveats) by `fn.length`.\n\n```js\nconst unary  = x => x         \u002F\u002F arity 1\nconst binary = (a, b) => a+b  \u002F\u002F arity 2\nbinary.length   \u002F\u002F 2\n```\n\nSome HOFs depend on arity — e.g. a `curry` helper invokes once enough args\narrive. **Pitfall:** \"expected\" arity (`length`) and \"actual\" args passed can\ndiffer freely in JS, since extra args are ignored and missing ones become\n`undefined`.\n",{"id":555,"difficulty":34,"q":556,"a":557},"variadic-functions","What is a variadic function?","A **variadic** function accepts a **variable number of arguments**. In modern\nJS you express this with a **rest parameter**; older code read `arguments`.\n\n```js\nconst max = (...nums) => nums.reduce((m, n) => n > m ? n : m, -Infinity)\nmax(3, 9, 2)        \u002F\u002F 9\nmax(...[5, 1, 8])   \u002F\u002F 8   — spread an array in\n\nMath.max(1, 2, 3)   \u002F\u002F built-in variadic example\n```\n\n**Pitfall:** spreading a **very large** array into a variadic call can exceed\nthe engine's argument limit and throw — use `reduce` over the array directly\nfor huge inputs.\n",{"id":559,"difficulty":34,"q":560,"a":561},"pass-by-value-reference","Are function arguments passed by value or by reference in JavaScript?","JavaScript is **pass-by-value** for everything — but for objects the \"value\"\nis a **reference** (a copy of the pointer). So you can mutate an object's\ncontents, but **reassigning** the parameter doesn't affect the caller.\n\n```js\nfunction mutate(o) { o.x = 1 }      \u002F\u002F caller sees x === 1\nfunction reassign(o) { o = { x: 9 } } \u002F\u002F caller unaffected\n\nconst a = {}; mutate(a)    \u002F\u002F a.x === 1\nconst b = {}; reassign(b)  \u002F\u002F b unchanged\n```\n\n**Pitfall:** this trips people who expect \"pass by reference\" — only the\n**reference is copied**, so reassigning the local parameter is invisible to\nthe caller.\n",{"id":563,"difficulty":67,"q":564,"a":565},"optional-arguments","What happens when you call a function with fewer or more arguments than declared?","JavaScript is **lenient about arity**. Missing arguments are `undefined`; extra\narguments are **ignored** (but still available via `arguments`\u002Frest).\n\n```js\nfunction f(a, b) { return [a, b] }\nf(1)         \u002F\u002F [1, undefined]   — missing -> undefined\nf(1, 2, 3)   \u002F\u002F [1, 2]           — extra 3 ignored by params\n```\n\nThis flexibility powers default parameters and variadic patterns. **Pitfall:**\nbecause no error is thrown, a typo dropping an argument fails silently with\n`undefined` downstream rather than at the call site.\n",{"id":567,"difficulty":50,"q":568,"a":569},"function-constructor","What is the Function constructor and why avoid it?","The **`Function` constructor** builds a function from **strings** at runtime:\n`new Function('a', 'b', 'return a + b')`. Like `eval`, it executes dynamic\ncode.\n\n```js\nconst add = new Function('a', 'b', 'return a + b')\nadd(2, 3)   \u002F\u002F 5\n\n\u002F\u002F does NOT close over local scope\nfunction outer() {\n  const x = 1\n  return new Function('return x')   \u002F\u002F ReferenceError when called\n}\n```\n\n**Avoid it** because: it bypasses **lexical scope** (only sees global), is a\n**security\u002FCSP risk**, and can't be optimized. Use real functions or closures\ninstead.\n",{"id":571,"difficulty":34,"q":572,"a":573},"generator-function-type","How is a generator function syntactically different from a normal function?","A **generator function** is declared with `function*` and can **pause** at\n`yield`. Calling it doesn't run the body — it returns an **iterator** object.\n\n```js\nfunction* gen() { yield 1; yield 2 }\nconst it = gen()        \u002F\u002F nothing logged yet\nit.next()               \u002F\u002F { value: 1, done: false }\n```\n\nIt's a distinct function *type* from declarations, expressions, and arrows.\n**Pitfall:** there is **no arrow generator** syntax — `*() => {}` is invalid;\ngenerators must use `function*`.\n",{"id":575,"difficulty":34,"q":576,"a":577},"async-function-type","What makes an async function a distinct function type?","An **`async` function** always **returns a Promise** and may use `await`\ninside to pause until a Promise settles. The `async` keyword changes the\nfunction's return contract.\n\n```js\nasync function load() {\n  const r = await fetch('\u002Fapi')   \u002F\u002F pauses without blocking the thread\n  return r.json()                  \u002F\u002F wrapped in a Promise automatically\n}\nload().then(data => \u002F* ... *\u002F data)   \u002F\u002F returns a Promise\n```\n\nArrows can be async too: `const f = async () => {}`. **Pitfall:** even a\n`return 5` inside an async function yields `Promise\u003C5>`, not `5`, so callers\nmust `await` or `.then` it.\n",{"id":579,"difficulty":34,"q":580,"a":581},"constructor-functions","What is a constructor function and how is `new` involved?","A **constructor function** is a regular function intended to be called with\n**`new`**. `new` creates a fresh object, sets its prototype, binds `this` to\nit, runs the body, and returns the object.\n\n```js\nfunction User(name) { this.name = name }   \u002F\u002F convention: capitalized\nconst u = new User('Ada')   \u002F\u002F this -> new object\nUser('Bob')                 \u002F\u002F no `new`: `this` is undefined\u002Fglobal\n```\n\n**Pitfall:** forgetting `new` is a classic bug — `this` leaks to the global\nobject (or throws in strict mode). ES6 **classes** make this safer by throwing\nif you call them without `new`.\n",{"id":583,"difficulty":50,"q":584,"a":585},"hoisting-fn-vs-class","How does hoisting differ between function declarations and function expressions assigned to let\u002Fconst?","**Function declarations** are fully hoisted — name and body — so they're\ncallable from the top of the scope. **`let`\u002F`const` expressions** are hoisted\nonly as **uninitialized bindings** in the temporal dead zone (TDZ).\n\n```js\ndecl()            \u002F\u002F works\nfunction decl() {}\n\nexpr()            \u002F\u002F ReferenceError — TDZ\nconst expr = () => {}\n```\n\nWith `var`, the variable hoists as `undefined`, so calling early gives a\n**TypeError** (`undefined is not a function`) instead. **Pitfall:** relying on\ndeclaration hoisting can obscure code order — many style guides discourage it.\n",{"id":587,"difficulty":34,"q":588,"a":589},"default-with-rest","Can you combine default parameters, destructuring, and rest in one signature?","Yes — JS lets you mix all parameter features, though **rest must come last**\nand a rest parameter **cannot have a default**.\n\n```js\nfunction config({ debug = false } = {}, ...plugins) {\n  return { debug, count: plugins.length }\n}\nconfig({ debug: true }, 'a', 'b')   \u002F\u002F { debug: true, count: 2 }\n\nfunction bad(...args = []) {}   \u002F\u002F SyntaxError — rest can't default\n```\n\n**Pitfall:** ordering matters — a default-valued parameter after a rest\nparameter is a syntax error, and forgetting the `= {}` on the destructured\nobject breaks no-argument calls.\n",{"id":591,"difficulty":34,"q":592,"a":593},"closures-over-params","How do parameters participate in closures?","Parameters are **local variables** of a function, so an inner function closes\nover them just like any other local. This is the basis of **factory functions**\nand partial application.\n\n```js\nfunction multiplier(factor) {        \u002F\u002F `factor` is a parameter...\n  return n => n * factor             \u002F\u002F ...captured by the returned closure\n}\nconst triple = multiplier(3)\ntriple(5)   \u002F\u002F 15   factor remembered\n```\n\nEach call to `multiplier` creates a **new** `factor` binding, so `double` and\n`triple` don't interfere. **Pitfall:** capturing a parameter that's later\nreassigned inside the outer function captures the **latest** value, not a\nsnapshot.\n",{"id":595,"difficulty":50,"q":596,"a":597},"getter-setter-functions","How do getter and setter functions differ from normal methods?","**Getters\u002Fsetters** are functions defined with `get`\u002F`set` that are invoked by\n**property access syntax** rather than a call — `obj.x` runs the getter,\n`obj.x = 1` runs the setter.\n\n```js\nconst temp = {\n  _c: 0,\n  get fahrenheit() { return this._c * 9\u002F5 + 32 },\n  set fahrenheit(f) { this._c = (f - 32) * 5\u002F9 }\n}\ntemp.fahrenheit = 212   \u002F\u002F calls setter\ntemp.fahrenheit         \u002F\u002F 212 — calls getter, no parentheses\n```\n\nThey enable **computed\u002Fvalidated properties** with a plain-property API.\n**Pitfall:** a getter that does heavy work runs on **every access**, and a\ngetter without a matching setter makes the property silently read-only (or\nthrows in strict mode on assignment).\n",{"id":599,"difficulty":50,"q":600,"a":601},"named-fn-expr-scope","Where is the name of a named function expression visible?","The name of a **named function expression** is bound **only inside the\nfunction's own body**, not in the surrounding scope. It exists so the function\ncan refer to itself.\n\n```js\nconst f = function rec(n) {\n  return n \u003C= 0 ? 0 : n + rec(n - 1)   \u002F\u002F `rec` visible here\n}\nf(3)    \u002F\u002F 6\nrec(3)  \u002F\u002F ReferenceError — `rec` not visible outside\n```\n\nThis makes recursion **safe against reassignment** of the outer variable\n(`f`). **Pitfall:** people expect the inner name to be accessible globally and\nare surprised by the ReferenceError outside.\n",{"description":32},"JavaScript function types and parameters interview questions — declarations vs expressions vs arrows, IIFEs, default and rest parameters, the arguments object, destructuring, arity, and first-class functions.","javascript\u002Ffunctions\u002Ffunction-types-parameters","Function Types & Parameters","MiP0SVPSrtWDSewPOQD8HZryX7lAoHl2TtUKXP5mnFQ",{"id":608,"title":609,"body":610,"description":32,"difficulty":34,"extension":35,"framework":10,"frameworkSlug":8,"meta":614,"navigation":37,"order":615,"path":616,"questions":617,"related":178,"seo":738,"seoDescription":739,"stem":740,"subtopic":741,"topic":19,"topicSlug":21,"updated":469,"__hash__":742},"qa\u002Fjavascript\u002Ffunctions\u002Fgenerators-iterators.md","Generators Iterators",{"type":29,"value":611,"toc":612},[],{"title":32,"searchDepth":20,"depth":20,"links":613},[],{},5,"\u002Fjavascript\u002Ffunctions\u002Fgenerators-iterators",[618,622,626,630,634,638,642,646,650,654,658,662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726,730,734],{"id":619,"difficulty":34,"q":620,"a":621},"iterator-protocol","What is the iterator protocol?","An **iterator** is any object with a **`next()`** method that returns\n`{ value, done }` on each call — `done: true` signals the end.\n\n```js\nconst it = {\n  i: 0,\n  next() {\n    return this.i \u003C 3\n      ? { value: this.i++, done: false }\n      : { value: undefined, done: true }   \u002F\u002F terminator\n  }\n}\nit.next()  \u002F\u002F { value: 0, done: false }\n```\n\nAnything implementing this shape can be driven manually, but usually you\nconsume iterators through `for...of`, spread, or destructuring.\n",{"id":623,"difficulty":34,"q":624,"a":625},"iterable-protocol","What is the iterable protocol and how does it relate to iterators?","An **iterable** is an object with a **`[Symbol.iterator]()`** method that\n*returns an iterator*. The iterable is the collection; the iterator is the\ncursor over it.\n\n```js\nconst range = {\n  [Symbol.iterator]() {\n    let n = 0\n    return { next: () => n \u003C 3\n      ? { value: n++, done: false }\n      : { value: undefined, done: true } }\n  }\n}\n[...range]   \u002F\u002F [0, 1, 2]  now spreadable \u002F for-of-able\n```\n\n`for...of`, spread, `Array.from`, and destructuring all call\n`Symbol.iterator` under the hood.\n",{"id":627,"difficulty":67,"q":628,"a":629},"builtin-iterables","Which built-in types are iterable?","Arrays, strings, `Map`, `Set`, `arguments`, `TypedArray`, and DOM\ncollections like `NodeList` — all ship a `Symbol.iterator`.\n\n```js\nfor (const ch of 'hi') {}        \u002F\u002F strings\nfor (const [k, v] of map) {}     \u002F\u002F Map yields [key, value]\n```\n\nNotably **plain objects are NOT iterable** — `for...of {}` throws. Use\n`Object.keys\u002Fvalues\u002Fentries`, which return iterable arrays.\n",{"id":631,"difficulty":67,"q":632,"a":633},"generator-basics","What is a generator function?","A **generator** (`function*`) is a function that can **pause and resume**.\nCalling it doesn't run the body — it returns a **generator object** (which\nis both an iterator and iterable). Each `next()` runs to the next `yield`.\n\n```js\nfunction* gen() {\n  yield 1\n  yield 2\n}\nconst g = gen()\ng.next()  \u002F\u002F { value: 1, done: false }\ng.next()  \u002F\u002F { value: 2, done: false }\ng.next()  \u002F\u002F { value: undefined, done: true }\n```\n\nGenerators are the easiest way to build custom iterators without writing\n`next()` by hand.\n",{"id":635,"difficulty":67,"q":636,"a":637},"yield-keyword","What does the yield keyword do?","**`yield`** pauses the generator and emits a value to the caller. Execution\nfreezes — local variables and position are preserved — until the next\n`next()` resumes it right after that `yield`.\n\n```js\nfunction* counter() {\n  let n = 0\n  while (true) yield n++   \u002F\u002F resumes here each time\n}\n```\n\nThis pause\u002Fresume is what makes lazy and infinite sequences possible.\n",{"id":639,"difficulty":34,"q":640,"a":641},"generator-is-iterable","Why can you use a generator directly in for...of and spread?","A generator object implements **both** protocols: it has `next()` (it's an\niterator) and a `Symbol.iterator` that returns itself (it's iterable).\n\n```js\nfunction* g() { yield 'a'; yield 'b' }\n[...g()]                 \u002F\u002F ['a', 'b']\nfor (const x of g()) {}  \u002F\u002F works directly\n```\n\nBecause it returns *itself* from `Symbol.iterator`, a generator is a\n**one-shot** iterable — once consumed it's exhausted.\n",{"id":643,"difficulty":34,"q":644,"a":645},"custom-iterable-with-generator","How do generators simplify making a class iterable?","Define `[Symbol.iterator]` as a **generator method**; `yield` the elements\nand the protocol bookkeeping is handled for you.\n\n```js\nclass Range {\n  constructor(s, e) { this.s = s; this.e = e }\n  *[Symbol.iterator]() {\n    for (let i = this.s; i \u003C this.e; i++) yield i  \u002F\u002F\n  }\n}\n[...new Range(1, 4)]   \u002F\u002F [1, 2, 3]\n```\n\nCompare to the manual `next()`\u002F`done` version — the generator removes all\nthe state plumbing.\n",{"id":647,"difficulty":34,"q":648,"a":649},"lazy-evaluation","What does it mean that generators are lazy?","Values are produced **on demand**, only when `next()` asks. Nothing is\ncomputed until consumed, and computation stops as soon as the consumer\nstops.\n\n```js\nfunction* squares() { let n = 1; while (true) yield n * n++ }\nconst it = squares()\nit.next().value  \u002F\u002F 1   — only this much computed\nit.next().value  \u002F\u002F 4\n```\n\nThis lets you model infinite or expensive sequences and pull just the\nfirst few elements without computing the rest.\n",{"id":651,"difficulty":34,"q":652,"a":653},"infinite-sequence","How do you build an infinite sequence safely?","A generator with an unbounded loop is fine **as long as the consumer\nbounds it**.\n\n```js\nfunction* naturals() { let n = 1; while (true) yield n++ }\nfunction take(it, k) {\n  const out = []\n  for (const x of it) { out.push(x); if (out.length === k) break }\n  return out\n}\ntake(naturals(), 3)   \u002F\u002F [1, 2, 3]\n```\n\nThe pitfall: `[...naturals()]` or `for...of` without a `break` will loop\nforever. Always cap consumption.\n",{"id":655,"difficulty":34,"q":656,"a":657},"yield-delegation","What does yield* (delegation) do?","**`yield*`** delegates to another iterable\u002Fgenerator — it yields *all* of\nits values in place, as if inlined.\n\n```js\nfunction* inner() { yield 1; yield 2 }\nfunction* outer() {\n  yield 0\n  yield* inner()   \u002F\u002F yields 1 then 2\n  yield 3\n}\n[...outer()]   \u002F\u002F [0, 1, 2, 3]\n```\n\nIt also forwards the delegated generator's **return value** as the result\nof the `yield*` expression, useful for composing generators.\n",{"id":659,"difficulty":34,"q":660,"a":661},"yield-delegation-any-iterable","Can yield* delegate to non-generator iterables?","Yes — `yield*` works on any iterable, so you can flatten arrays, strings,\nSets, etc.\n\n```js\nfunction* flatten(arrs) {\n  for (const a of arrs) yield* a   \u002F\u002F spread each array's items\n}\n[...flatten([[1, 2], [3], [4, 5]])]  \u002F\u002F [1, 2, 3, 4, 5]\n```\n\nThis makes recursive flattening of nested structures elegant — just\n`yield* flatten(child)` for sub-arrays.\n",{"id":663,"difficulty":50,"q":664,"a":665},"passing-values-into-next","How do you pass a value back into a generator?","The argument to **`next(value)`** becomes the *result* of the `yield`\nexpression that the generator is paused on — two-way communication.\n\n```js\nfunction* convo() {\n  const name = yield 'What is your name?'\n  yield `Hello, ${name}!`\n}\nconst c = convo()\nc.next().value        \u002F\u002F 'What is your name?'\nc.next('Ada').value   \u002F\u002F 'Hello, Ada!'  'Ada' became `name`\n```\n\nGotcha: the **first** `next()` argument is ignored — there's no paused\n`yield` yet to receive it.\n",{"id":667,"difficulty":50,"q":668,"a":669},"generator-return-method","What does the generator's return() method do?","`gen.return(v)` forces the generator to finish early, yielding\n`{ value: v, done: true }` and running any `finally` blocks for cleanup.\n\n```js\nfunction* g() {\n  try { yield 1; yield 2 }\n  finally { console.log('cleanup') }  \u002F\u002F runs on early return\n}\nconst it = g()\nit.next()        \u002F\u002F { value: 1, done: false }\nit.return(99)    \u002F\u002F logs 'cleanup'; { value: 99, done: true }\n```\n\n`for...of` calls `return()` automatically when you `break`, so resources\nget released.\n",{"id":671,"difficulty":50,"q":672,"a":673},"generator-throw-method","What does the generator's throw() method do?","`gen.throw(err)` injects an exception **at the paused `yield`**, as if the\n`yield` itself threw — the generator can `try\u002Fcatch` it.\n\n```js\nfunction* g() {\n  try { yield 1 }\n  catch (e) { yield `caught ${e}` }  \u002F\u002F\n}\nconst it = g()\nit.next()          \u002F\u002F { value: 1 }\nit.throw('boom')   \u002F\u002F { value: 'caught boom', done: false }\n```\n\nIf the generator doesn't catch it, the error propagates to the caller of\n`throw()`.\n",{"id":675,"difficulty":34,"q":676,"a":677},"return-value-in-generator","What happens to a return statement inside a generator?","A `return x` sets `{ value: x, done: true }` on the final `next()` — but\n**`for...of` and spread ignore that value**; they only collect yielded\nvalues.\n\n```js\nfunction* g() { yield 1; return 99 }\n[...g()]                  \u002F\u002F [1]  — 99 dropped\nconst it = g()\nit.next()                 \u002F\u002F { value: 1, done: false }\nit.next()                 \u002F\u002F { value: 99, done: true }  visible here\n```\n\nTo observe the return value you must drive `next()` manually or capture it\nvia `yield*`.\n",{"id":679,"difficulty":50,"q":680,"a":681},"state-machine","How can a generator model a state machine?","Sequential `yield`s with a surrounding loop naturally encode states —\nexecution position *is* the current state, so you avoid explicit state\nvariables.\n\n```js\nfunction* traffic() {\n  while (true) {\n    yield 'green'; yield 'yellow'; yield 'red'  \u002F\u002F cycles states\n  }\n}\nconst light = traffic()\nlight.next().value  \u002F\u002F 'green'\nlight.next().value  \u002F\u002F 'yellow'\n```\n\nThe generator remembers where it paused, so each `next()` advances the\nmachine one transition with no bookkeeping.\n",{"id":683,"difficulty":34,"q":684,"a":685},"generator-vs-array","When is a generator better than building an array?","When the sequence is **large, infinite, or expensive**, and the consumer\nmay not need all of it. A generator streams values lazily; an array\nmaterializes everything up front.\n\n```js\n\u002F\u002F reads a huge file line by line without loading it all\nfunction* lines(text) {\n  for (const line of text.split('\\n')) yield line.trim()\n}\n```\n\nFor small, fully-consumed collections an array is simpler and faster to\nindex — generators shine on streaming\u002Fpipeline workloads.\n",{"id":687,"difficulty":34,"q":688,"a":689},"early-break-cleanup","What happens to a generator when you break out of for...of early?","`for...of` calls the iterator's **`return()`** on `break`, `throw`, or an\nexception — so a generator's `finally` runs and resources are released.\n\n```js\nfunction* withResource() {\n  try { while (true) yield acquire() }\n  finally { release() }   \u002F\u002F runs even on early break\n}\nfor (const x of withResource()) { if (done) break }  \u002F\u002F release() called\n```\n\nThis automatic cleanup is a key reason to wrap resource handling in\ntry\u002Ffinally inside generators.\n",{"id":691,"difficulty":34,"q":692,"a":693},"spread-consumes-iterator","Why does iterating the same generator twice yield nothing the second time?","A generator object is a **single-use** iterator — once `done`, it stays\ndone. It doesn't restart.\n\n```js\nconst g = (function* () { yield 1; yield 2 })()\n[...g]   \u002F\u002F [1, 2]\n[...g]   \u002F\u002F []  already exhausted\n```\n\nTo re-iterate, expose a **factory** (a function returning a fresh\ngenerator) or a class whose `[Symbol.iterator]` creates a new one each\ncall.\n",{"id":695,"difficulty":50,"q":696,"a":697},"async-generator","What is an async generator?","An **`async function*`** can `await` inside and `yield` values\nasynchronously. Its `next()` returns a **Promise** of `{ value, done }`,\nand you consume it with **`for await...of`**.\n\n```js\nasync function* pages(url) {\n  let next = url\n  while (next) {\n    const res = await fetch(next)   \u002F\u002F await inside\n    const data = await res.json()\n    yield data.items\n    next = data.nextPage\n  }\n}\nfor await (const items of pages('\u002Fapi')) { \u002F* ... *\u002F }\n```\n\nPerfect for paginated APIs and streams where each chunk arrives over time.\n",{"id":699,"difficulty":50,"q":700,"a":701},"for-await-of","What is for await...of and where can you use it?","It iterates an **async iterable** (one with `Symbol.asyncIterator`),\nawaiting each `next()` Promise before the loop body runs. It must be inside\nan `async` function.\n\n```js\nasync function read(stream) {\n  for await (const chunk of stream) {   \u002F\u002F awaits each chunk\n    process(chunk)\n  }\n}\n```\n\nIt also works on a plain array of Promises, awaiting each in turn — handy\nfor sequential async processing.\n",{"id":703,"difficulty":50,"q":704,"a":705},"symbol-asynciterator","How does Symbol.asyncIterator differ from Symbol.iterator?","`Symbol.iterator` returns an iterator whose `next()` yields plain\n`{ value, done }`; `Symbol.asyncIterator` returns one whose `next()` yields\na **Promise** of that. `for await...of` looks for `asyncIterator` first,\nfalling back to the sync one.\n\n```js\nconst stream = {\n  async *[Symbol.asyncIterator]() {\n    yield await getChunk()   \u002F\u002F async iterable\n  }\n}\n```\n\nUse the async variant when each value depends on I\u002FO or timing.\n",{"id":707,"difficulty":34,"q":708,"a":709},"generator-memory","How do generators help with memory usage?","They hold only the **current** value and the suspended call frame, not the\nwhole sequence — so you can process gigabytes by streaming a constant\namount of memory.\n\n```js\nfunction* range(n) { for (let i = 0; i \u003C n; i++) yield i }\nlet sum = 0\nfor (const i of range(1e9)) sum += i   \u002F\u002F no billion-element array\n```\n\nBuilding `Array.from({length: 1e9})` first would blow the heap; the\ngenerator never allocates it.\n",{"id":711,"difficulty":50,"q":712,"a":713},"generator-pipeline","How do you compose generators into a processing pipeline?","Chain generators that each take an iterable and yield a transformed one —\nlazy `map`\u002F`filter` that never build intermediate arrays.\n\n```js\nfunction* map(it, f) { for (const x of it) yield f(x) }\nfunction* filter(it, p) { for (const x of it) if (p(x)) yield x }\n\nconst result = map(\n  filter(range(100), n => n % 2 === 0),\n  n => n * n\n)   \u002F\u002F nothing computed until consumed\n```\n\nEach stage pulls one value at a time, so a pipeline over an infinite source\nstill works.\n",{"id":715,"difficulty":50,"q":716,"a":717},"generator-this-binding","Can a generator be an arrow function?","No — there is **no arrow generator syntax**. Generators must be\n`function*` declarations\u002Fexpressions or `*method()` shorthand in\nobjects\u002Fclasses.\n\n```js\nconst g = function* () { yield 1 }      \u002F\u002F expression\nconst obj = { *gen() { yield 1 } }      \u002F\u002F method shorthand\n\u002F\u002F const bad = *() => {}                \u002F\u002F SyntaxError\n```\n\nAs object\u002Fclass methods, generators get `this` from the call site like any\nmethod, which is exactly why arrow generators aren't needed.\n",{"id":719,"difficulty":34,"q":720,"a":721},"iterator-helpers","What are iterator helper methods?","Modern engines add lazy helper methods directly on iterators —\n`map`, `filter`, `take`, `drop`, `flatMap`, `reduce`, `toArray` — so you\nget array-like chaining without materializing arrays.\n\n```js\nfunction* naturals() { let n = 1; while (true) yield n++ }\nnaturals()\n  .filter(n => n % 2)\n  .map(n => n * n)\n  .take(3)\n  .toArray()           \u002F\u002F [1, 9, 25]  lazy, bounded by take\n```\n\nThey make working with infinite generators ergonomic; check target support\nas adoption is recent.\n",{"id":723,"difficulty":34,"q":724,"a":725},"manual-vs-generator-iterator","Why prefer a generator over hand-writing an iterator object?","A generator manages all the protocol state for you — the `{ value, done }`\nshape, the `done` terminator, returning itself from `Symbol.iterator`, and\n`return()`\u002F`throw()` semantics. Hand-rolled iterators are verbose and\nerror-prone.\n\n```js\n\u002F\u002F generator: 3 lines vs a dozen for the manual next()\u002Fdone version\nfunction* range(s, e) { for (let i = s; i \u003C e; i++) yield i }\n```\n\nReserve manual iterators for cases needing unusual control over the\nprotocol; otherwise use a generator.\n",{"id":727,"difficulty":34,"q":728,"a":729},"destructure-iterator","How do destructuring and spread interact with iterators?","Both consume an iterable via its iterator. Destructuring pulls only as many\nvalues as the pattern needs; spread drains it fully.\n\n```js\nfunction* g() { yield 1; yield 2; yield 3 }\nconst [a, b] = g()     \u002F\u002F pulls 2, iterator left at 3\nconst all = [...g()]   \u002F\u002F [1, 2, 3] — fully drained\n```\n\nBecause destructuring stops early, `const [first] = infinite()` is safe,\nbut `const [...rest] = infinite()` hangs.\n",{"id":731,"difficulty":50,"q":732,"a":733},"generator-return-from-yieldstar","How do you capture the return value of a delegated generator?","`yield*` evaluates to the **return value** of the inner generator, letting\nyou build sub-results.\n\n```js\nfunction* inner() { yield 1; return 'done' }\nfunction* outer() {\n  const result = yield* inner()   \u002F\u002F result === 'done'\n  yield result\n}\n[...outer()]   \u002F\u002F [1, 'done']\n```\n\nThis is how generators compose computations: the yielded stream flows\nthrough while the return value bubbles back to the delegator.\n",{"id":735,"difficulty":34,"q":736,"a":737},"when-not-to-use-generators","When should you avoid generators?","For small, fully-consumed collections, plain arrays\u002Farray methods are\nsimpler, faster to index, and easier to debug. Generators add overhead per\n`next()` call and can't be randomly accessed or reused.\n\n```js\n\u002F\u002F overkill — just use an array\nfunction* three() { yield 1; yield 2; yield 3 }\nconst arr = [1, 2, 3]   \u002F\u002F clearer here\n```\n\nReach for generators when you genuinely need laziness, infinite\u002Fstreaming\ndata, two-way communication, or memory-bounded processing.\n",{"description":32},"JavaScript generators and iterators interview questions — the iterator and iterable protocols, function* and yield, yield* delegation, lazy and infinite sequences, two-way communication and async generators.","javascript\u002Ffunctions\u002Fgenerators-iterators","Generators & Iterators","PjkAQb6KJH099D5oXrnCdLp3so5iSdXLlO3hoWit9iw",1781808674571]