[{"data":1,"prerenderedAt":3417},["ShallowReactive",2],{"fw-javascript":3},{"framework":4,"topics":15,"qa":78},{"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",[16,24,33,42,51,60,69],{"id":17,"description":18,"extension":7,"frameworkSlug":8,"meta":19,"name":20,"order":11,"slug":21,"stem":22,"__hash__":23},"topics\u002Ftopics\u002Fjavascript-fundamentals.yml","Variables, scope, hoisting, data types and type coercion — the bedrock concepts every JavaScript interview starts with.",{},"Fundamentals","fundamentals","topics\u002Fjavascript-fundamentals","iD2M8X27iFyEzm-j-SDyMRdEhVFmIAx80cJzIDxm310",{"id":25,"description":26,"extension":7,"frameworkSlug":8,"meta":27,"name":28,"order":29,"slug":30,"stem":31,"__hash__":32},"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",{"id":34,"description":35,"extension":7,"frameworkSlug":8,"meta":36,"name":37,"order":38,"slug":39,"stem":40,"__hash__":41},"topics\u002Ftopics\u002Fjavascript-async.yml","Callbacks, promises, async\u002Fawait and the event loop — how JavaScript handles non-blocking work behind the scenes.",{},"Asynchronous JavaScript",3,"async","topics\u002Fjavascript-async","N36EMzo9wWwCjQeB0JVso1oDGm5N7nWY0Cb9ec38Ph0",{"id":43,"description":44,"extension":7,"frameworkSlug":8,"meta":45,"name":46,"order":47,"slug":48,"stem":49,"__hash__":50},"topics\u002Ftopics\u002Fjavascript-objects.yml","Object creation and properties, the prototype chain, prototypal inheritance and how the new operator builds objects — the heart of JavaScript's object model.",{},"Objects & Prototypes",4,"objects","topics\u002Fjavascript-objects","MljHH-t_2tN7XAsE57kKvNFYqNiVrpxWJD6_LiN-Ltk",{"id":52,"description":53,"extension":7,"frameworkSlug":8,"meta":54,"name":55,"order":56,"slug":57,"stem":58,"__hash__":59},"topics\u002Ftopics\u002Fjavascript-classes.yml","ES6 class syntax, inheritance with extends and super, static members, private fields, getters\u002Fsetters and mixins — object-oriented JavaScript built on prototypes.",{},"Classes & OOP",5,"classes","topics\u002Fjavascript-classes","2Dc4r7D4tXqZpTXsCLGK8xzI7Sds3kxb1nsez87RxFo",{"id":61,"description":62,"extension":7,"frameworkSlug":8,"meta":63,"name":64,"order":65,"slug":66,"stem":67,"__hash__":68},"topics\u002Ftopics\u002Fjavascript-arrays.yml","Creating and iterating arrays with map, filter and reduce, mutation versus immutability, searching and sorting, and array destructuring and spread — the everyday tools for working with collections in JavaScript.",{},"Arrays & Iteration",6,"arrays","topics\u002Fjavascript-arrays","eJvg0ZBiFKP3QUymQDEwMgBS_wi33V9eQLpIGNETmEY",{"id":70,"description":71,"extension":7,"frameworkSlug":8,"meta":72,"name":73,"order":74,"slug":75,"stem":76,"__hash__":77},"topics\u002Ftopics\u002Fjavascript-modern.yml","The ergonomic features that define modern JavaScript — destructuring and spread\u002Frest, optional chaining and nullish coalescing, template literals and tagged templates, and Symbols for unique keys and protocol hooks.",{},"Modern JavaScript (ES6+)",7,"modern","topics\u002Fjavascript-modern","7OY2hfQ7yWvC9ZJ6_podaZledkcVcsfjkOUxh5L34a8",[79,230,369,508,643,791,941,1052,1171,1278,1389,1539,1674,1808,1946,2092,2238,2385,2523,2657,2786,2921,3036,3170,3287],{"id":80,"title":81,"body":82,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":90,"navigation":91,"order":11,"path":92,"questions":93,"related":224,"seo":225,"seoDescription":226,"stem":227,"subtopic":81,"topic":64,"topicSlug":66,"updated":228,"__hash__":229},"qa\u002Fjavascript\u002Farrays\u002Farray-methods.md","Array Methods",{"type":83,"value":84,"toc":85},"minimark",[],{"title":86,"searchDepth":29,"depth":29,"links":87},"",[],"medium","md",{},true,"\u002Fjavascript\u002Farrays\u002Farray-methods",[94,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220],{"id":95,"difficulty":96,"q":97,"a":98},"map-basics","easy","What does Array.prototype.map do?","**map** creates a **new array** by calling a callback on every element and\ncollecting the return values. It does not mutate the original and always\nreturns an array of the **same length**.\n\n```js\nconst nums = [1, 2, 3]\nconst doubled = nums.map(n => n * 2) \u002F\u002F [2, 4, 6]\nnums \u002F\u002F [1, 2, 3] — unchanged\n```\n\nA common pitfall is using `map` purely for side effects (logging, pushing\nelsewhere). If you don't use the returned array, use `forEach` instead — it\nsignals intent and avoids allocating a throwaway array.\n",{"id":100,"difficulty":96,"q":101,"a":102},"filter-basics","What does Array.prototype.filter do?","**filter** returns a **new array** containing only the elements for which the\ncallback returns a **truthy** value. Length is less than or equal to the\noriginal.\n\n```js\nconst nums = [1, 2, 3, 4]\nconst evens = nums.filter(n => n % 2 === 0) \u002F\u002F [2, 4]\n```\n\nGotcha: the predicate must return a boolean-ish value. Forgetting `return` in\na block body silently filters everything out, since `undefined` is falsy:\n\n```js\nnums.filter(n => { n % 2 === 0 }) \u002F\u002F [] — no return\n```\n",{"id":104,"difficulty":96,"q":105,"a":106},"foreach-basics","What is forEach used for and what does it return?","**forEach** runs a callback once per element for **side effects**. It always\nreturns **undefined** — you can't chain off it.\n\n```js\n[1, 2, 3].forEach(n => console.log(n))\n```\n\nTwo gotchas: you **cannot break** out of `forEach` (use a `for...of` or `some`\nif you need early exit), and it **skips holes** in sparse arrays. If you need\na transformed result, reach for `map` instead.\n",{"id":108,"difficulty":88,"q":109,"a":110},"reduce-basics","How does Array.prototype.reduce work?","**reduce** folds an array into a **single value** by threading an accumulator\nthrough a callback `(acc, cur) => newAcc`. You pass an **initial value** as the\nsecond argument.\n\n```js\nconst sum = [1, 2, 3, 4].reduce((acc, n) => acc + n, 0) \u002F\u002F 10\n```\n\nPitfall: **omitting the initial value** makes reduce use the first element as\nthe seed and start at index 1 — and it **throws** on an empty array. Always\npass an explicit initial value unless you have a specific reason not to.\n",{"id":112,"difficulty":88,"q":113,"a":114},"reduce-no-initial","What happens if you call reduce without an initial value on an empty array?","It throws a **TypeError: Reduce of empty array with no initial value**. With no\nseed, reduce needs at least one element to start from.\n\n```js\n[].reduce((a, b) => a + b)    \u002F\u002F TypeError\n[].reduce((a, b) => a + b, 0) \u002F\u002F 0\n```\n\nThis is why supplying an initial value is a best practice — it makes the\noperation total (defined for all inputs) and pins down the accumulator's type.\n",{"id":116,"difficulty":88,"q":117,"a":118},"reduceright","What is reduceRight and when would you use it?","**reduceRight** is identical to `reduce` but processes elements from **right to\nleft**. It matters when the operation is **not associative** or when order of\ncomposition matters.\n\n```js\n\u002F\u002F function composition: f(g(h(x)))\nconst compose = (...fns) => x =>\n  fns.reduceRight((acc, fn) => fn(acc), x)\n\nconst f = compose(n => n + 1, n => n * 2)\nf(3) \u002F\u002F 7  -> (3*2)+1\n```\n\nFor plain addition the direction is irrelevant; for string building, division,\nor composition it changes the result.\n",{"id":120,"difficulty":96,"q":121,"a":122},"some-every","What is the difference between some and every?","**some** returns `true` if **at least one** element passes the predicate;\n**every** returns `true` only if **all** elements pass. Both **short-circuit**.\n\n```js\n[1, 2, 3].some(n => n > 2)  \u002F\u002F true  (stops at 3)\n[1, 2, 3].every(n => n > 0) \u002F\u002F true\n[1, 2, 3].every(n => n > 1) \u002F\u002F false (stops at 1)\n```\n\nEdge case: `every` on an **empty array** returns `true` (vacuous truth) and\n`some` returns `false`. This trips people up in validation code.\n",{"id":124,"difficulty":96,"q":125,"a":126},"find-findindex","What is the difference between find and findIndex?","**find** returns the **first element** that satisfies the predicate, or\n`undefined`. **findIndex** returns its **index**, or `-1`.\n\n```js\nconst users = [{ id: 1 }, { id: 2 }]\nusers.find(u => u.id === 2)      \u002F\u002F { id: 2 }\nusers.findIndex(u => u.id === 2) \u002F\u002F 1\nusers.find(u => u.id === 9)      \u002F\u002F undefined\n```\n\nUse `find` when you want the object itself; use `findIndex` when you need the\nposition (e.g. to splice or replace it).\n",{"id":128,"difficulty":88,"q":129,"a":130},"findlast","What do findLast and findLastIndex do?","They mirror `find`\u002F`findIndex` but search from the **end** of the array\nbackward, returning the **last** matching element or its index.\n\n```js\nconst nums = [1, 5, 3, 5, 2]\nnums.findLast(n => n === 5)      \u002F\u002F 5  (the second 5)\nnums.findLastIndex(n => n === 5) \u002F\u002F 3\n```\n\nBefore these (ES2023) you'd reverse a copy or loop manually. They avoid an\nextra `[...arr].reverse().find(...)` allocation and keep the original index\nmeaningful.\n",{"id":132,"difficulty":96,"q":133,"a":134},"indexof-vs-find","When should you use find versus indexOf?","Use **indexOf** for **primitive equality** (it uses strict `===`), and **find**\nwhen you need a **predicate** (matching by a property or condition).\n\n```js\n[10, 20, 30].indexOf(20)              \u002F\u002F 1\nusers.find(u => u.name === 'Ann')     \u002F\u002F predicate match\n```\n\n`indexOf` can't match objects by content, only by reference, so for arrays of\nobjects you almost always want `find`\u002F`findIndex`.\n",{"id":136,"difficulty":88,"q":137,"a":138},"flat","What does Array.prototype.flat do?","**flat** returns a **new array** with sub-array elements concatenated up to a\ngiven **depth** (default `1`). It does not mutate.\n\n```js\n[1, [2, [3, [4]]]].flat()        \u002F\u002F [1, 2, [3, [4]]]\n[1, [2, [3, [4]]]].flat(2)       \u002F\u002F [1, 2, 3, [4]]\n[1, [2, [3]]].flat(Infinity)     \u002F\u002F [1, 2, 3] fully flatten\n```\n\nUse `flat(Infinity)` for arbitrarily nested structures. It also removes empty\nslots in sparse arrays as a side effect.\n",{"id":140,"difficulty":88,"q":141,"a":142},"flatmap","What is flatMap and how does it differ from map then flat?","**flatMap** maps each element then flattens the result by **one level**, in a\nsingle pass. It's equivalent to `map(...).flat()` but more efficient and\nexpressive.\n\n```js\nconst sentences = ['a b', 'c d']\nsentences.flatMap(s => s.split(' ')) \u002F\u002F ['a', 'b', 'c', 'd']\n```\n\nIt only flattens **one level**. A neat trick: returning `[]` from the callback\n**drops** an element, letting flatMap act as a combined map+filter.\n",{"id":144,"difficulty":88,"q":145,"a":146},"array-from","What does Array.from do?","**Array.from** creates a real array from any **iterable** or **array-like**\nobject (one with a `length` and indexed keys). It accepts an optional mapping\nfunction as a second argument.\n\n```js\nArray.from('abc')              \u002F\u002F ['a', 'b', 'c']\nArray.from(new Set([1, 1, 2])) \u002F\u002F [1, 2]\nArray.from({ length: 3 }, (_, i) => i) \u002F\u002F [0, 1, 2]\n```\n\nThe mapping form is handy for generating sequences and avoids creating an\nintermediate array, unlike `[...iterable].map(fn)`.\n",{"id":148,"difficulty":96,"q":149,"a":150},"array-of","Why does Array.of exist when we have the Array constructor?","**Array.of** creates an array from its arguments **consistently**, fixing a\nquirk of `new Array()`: a single numeric argument is treated as a **length**,\nnot an element.\n\n```js\nArray(3)      \u002F\u002F [ \u003C3 empty items> ] — length 3\nArray.of(3)   \u002F\u002F [3]\nArray(1, 2)   \u002F\u002F [1, 2] — but inconsistent with Array(3)\nArray.of(1, 2)\u002F\u002F [1, 2]\n```\n\n`Array.of` always treats arguments as elements, so it's safer in generic code.\n",{"id":152,"difficulty":88,"q":153,"a":154},"entries-keys-values","What do entries, keys, and values return on an array?","They return **array iterators**, not arrays. `keys()` yields indices,\n`values()` yields elements, and `entries()` yields `[index, value]` pairs.\n\n```js\nconst arr = ['a', 'b']\nfor (const [i, v] of arr.entries()) {\n  console.log(i, v) \u002F\u002F 0 'a', then 1 'b'\n}\n[...arr.keys()]   \u002F\u002F [0, 1]\n[...arr.values()] \u002F\u002F ['a', 'b']\n```\n\n`entries()` is the clean way to get the index inside a `for...of` loop without\na manual counter.\n",{"id":156,"difficulty":88,"q":157,"a":158},"chaining","How does method chaining work with array methods?","Because **map**, **filter**, **slice**, and friends each return a **new array**,\nyou can chain them into a readable pipeline.\n\n```js\nconst result = users\n  .filter(u => u.active)\n  .map(u => u.name)\n  .sort() \u002F\u002F active users' names, sorted\n```\n\nTradeoff: each step allocates a new array and does a full pass. For huge arrays\nor hot paths a single `reduce` (or a plain loop) can avoid the intermediate\narrays, at the cost of readability.\n",{"id":160,"difficulty":161,"q":162,"a":163},"reduce-to-object","hard","How do you use reduce to build an object from an array?","Seed the accumulator with `{}` and assign keys as you go. This is the canonical\nway to **index** a list by id.\n\n```js\nconst users = [{ id: 1, name: 'A' }, { id: 2, name: 'B' }]\nconst byId = users.reduce((acc, u) => {\n  acc[u.id] = u\n  return acc\n}, {}) \u002F\u002F { 1: {...}, 2: {...} }\n```\n\nFor this exact case, `Object.fromEntries(users.map(u => [u.id, u]))` is often\nclearer. Reserve reduce-to-object for logic that doesn't fit a simple map.\n",{"id":165,"difficulty":161,"q":166,"a":167},"reduce-grouping","How do you group array items by a key?","Use **reduce** to accumulate into buckets, initializing each bucket lazily.\n\n```js\nconst items = [{ type: 'a', v: 1 }, { type: 'b', v: 2 }, { type: 'a', v: 3 }]\nconst grouped = items.reduce((acc, item) => {\n  (acc[item.type] ??= []).push(item) \u002F\u002F create bucket then push\n  return acc\n}, {})\n\u002F\u002F { a: [{a,1},{a,3}], b: [{b,2}] }\n```\n\nModern engines also offer **Object.groupBy(items, item => item.type)**, which\ndoes exactly this without the boilerplate.\n",{"id":169,"difficulty":88,"q":170,"a":171},"reduce-flatten","How can reduce flatten an array of arrays?","Concatenate each sub-array into an accumulator:\n\n```js\nconst nested = [[1, 2], [3], [4, 5]]\nconst flat = nested.reduce((acc, sub) => acc.concat(sub), []) \u002F\u002F [1,2,3,4,5]\n```\n\nIn practice prefer the dedicated `nested.flat()` — it's clearer and faster. The\nreduce version is mostly useful as an interview demonstration of how flattening\nworks under the hood, or when you need custom merge logic per chunk.\n",{"id":173,"difficulty":96,"q":174,"a":175},"map-index","How do you access the index inside map, filter, or forEach?","Every iteration callback receives `(element, index, array)`. The second\nparameter is the index.\n\n```js\n['a', 'b', 'c'].map((char, i) => `${i}:${char}`) \u002F\u002F ['0:a', '1:b', '2:c']\n```\n\nGotcha: passing a method like `arr.map(parseInt)` breaks because `parseInt`\nreceives the index as its radix argument: `['1','2','3'].map(parseInt)` gives\n`[1, NaN, NaN]`. Wrap it: `arr.map(Number)` or `arr.map(s => parseInt(s, 10))`.\n",{"id":177,"difficulty":96,"q":178,"a":179},"map-vs-foreach","When should you choose map over forEach?","Choose **map** when you want a **transformed array** back; choose **forEach**\nwhen you only need **side effects** and ignore the return value.\n\n```js\nconst upper = names.map(n => n.toUpperCase()) \u002F\u002F need result\nnames.forEach(n => console.log(n))            \u002F\u002F side effect only\n```\n\nUsing `map` without consuming the result is a code smell — it implies a\ntransformation that's thrown away, confusing readers and wasting an allocation.\n",{"id":181,"difficulty":161,"q":182,"a":183},"chaining-vs-loop","What are the performance tradeoffs of chaining versus a single loop?","Each chained method (`filter().map()`) does a **full pass** and **allocates a\nnew array**. A single `for` loop or one `reduce` does one pass with no\nintermediate arrays.\n\n```js\n\u002F\u002F 2 passes, 2 arrays\narr.filter(x => x > 0).map(x => x * 2)\n\u002F\u002F 1 pass, 1 array\narr.reduce((acc, x) => (x > 0 && acc.push(x * 2), acc), [])\n```\n\nFor typical data sizes the difference is negligible and readability wins. Only\nfuse into a loop when profiling shows it matters.\n",{"id":185,"difficulty":96,"q":186,"a":187},"chaining-empty","What happens when you chain methods on an empty array?","Iteration methods on an empty array simply **don't call the callback** and\nreturn an empty (or seeded) result — no errors.\n\n```js\n[].map(x => x.boom)        \u002F\u002F [] — callback never runs\n[].filter(Boolean)         \u002F\u002F []\n[].reduce((a, b) => a + b) \u002F\u002F throws — no initial value\n```\n\nThe only landmine is `reduce` with no initial value, which throws on empty\ninput. Everything else degrades gracefully to an empty result.\n",{"id":189,"difficulty":88,"q":190,"a":191},"which-method","How do you decide which iteration method to use?","Match the method to the **shape of the result** you want:\n\n```text\ntransform each -> map\nkeep a subset -> filter\none value -> reduce\na single match -> find \u002F findIndex\nyes\u002Fno across all -> some \u002F every\nside effects only -> forEach (or for...of)\n```\n\nPicking the right method makes intent obvious. Reaching for `reduce` when\n`map` or `filter` fits is a common over-engineering mistake.\n",{"id":193,"difficulty":88,"q":194,"a":195},"chaining-readability","How can you keep long method chains readable?","Put **each step on its own line**, name intermediate results when a chain gets\nlong, and keep callbacks small (extract named functions for complex logic).\n\n```js\nconst activeNames = users\n  .filter(isActive)      \u002F\u002F named predicate\n  .map(u => u.name)\n  .sort(byAlpha)\n```\n\nA chain longer than 3-4 steps, or with multi-line callbacks, is often clearer\nsplit into named variables. Optimize for the next reader, not for fewer lines.\n",{"id":197,"difficulty":96,"q":198,"a":199},"copy-with-map","Does map produce a deep or shallow copy?","`map` produces a **new array**, but the elements are the **same references** for\nobjects — it's a **shallow** transform.\n\n```js\nconst arr = [{ n: 1 }]\nconst copy = arr.map(o => o)\ncopy[0].n = 99\narr[0].n \u002F\u002F 99 — same object reference\n```\n\nTo copy each object too, map to a new object: `arr.map(o => ({ ...o }))`. For\ndeeply nested data, `structuredClone` per element is safer.\n",{"id":201,"difficulty":161,"q":202,"a":203},"side-effects-in-map","Why are side effects inside map considered an anti-pattern?","`map` is meant to be a **pure transformation**: input array in, new array out.\nMutating external state or other elements inside the callback makes the code\nhard to reason about and order-dependent.\n\n```js\nlet total = 0\narr.map(x => { total += x; return x }) \u002F\u002F hidden side effect\n```\n\nUse `forEach`\u002F`for...of` for side effects and `reduce` for accumulation. Keep\n`map` pure so chains stay predictable and refactor-safe.\n",{"id":205,"difficulty":88,"q":206,"a":207},"chaining-find-after-filter","Why is filter().find() sometimes wasteful, and what's better?","`filter` walks the **entire array** building a new one, then `find` walks again.\nIf you only need the first match, `find` alone short-circuits on the first hit.\n\n```js\narr.filter(x => x > 10)[0]   \u002F\u002F full pass + array allocation\narr.find(x => x > 10)        \u002F\u002F stops at first match\n```\n\nSimilarly, prefer `some` over `filter(...).length > 0`. Choosing a\nshort-circuiting method avoids unnecessary work on large arrays.\n",{"id":209,"difficulty":88,"q":210,"a":211},"reduce-max","How do you find the maximum value with reduce?","Thread the running maximum through the accumulator:\n\n```js\nconst max = [3, 7, 2, 9, 4].reduce((m, n) => (n > m ? n : m), -Infinity)\n\u002F\u002F 9\n```\n\nSeeding with `-Infinity` keeps it correct even when all values are negative.\nFor plain numbers `Math.max(...arr)` is shorter, but it risks a stack overflow\non very large arrays — reduce stays safe there.\n",{"id":213,"difficulty":96,"q":214,"a":215},"array-isarray","How do you reliably check if a value is an array?","Use **Array.isArray**. `typeof []` returns `'object'`, so it can't distinguish\narrays from other objects.\n\n```js\nArray.isArray([1, 2]) \u002F\u002F true\nArray.isArray('ab')   \u002F\u002F false\ntypeof []             \u002F\u002F 'object' — useless here\n```\n\n`Array.isArray` also works correctly across **iframes\u002Frealms**, where\n`instanceof Array` can fail because each realm has its own `Array` constructor.\n",{"id":217,"difficulty":161,"q":218,"a":219},"foreach-async","Why does forEach not work well with async\u002Fawait?","`forEach` **ignores the promise** returned by an async callback, so it does not\nwait — the loop finishes before any async work completes.\n\n```js\nids.forEach(async id => { await save(id) }) \u002F\u002F doesn't await\n\u002F\u002F \"done\" logs before saves finish\n\nfor (const id of ids) { await save(id) }    \u002F\u002F sequential\nawait Promise.all(ids.map(id => save(id)))  \u002F\u002F parallel\n```\n\nUse a `for...of` loop for sequential awaits, or `map` + `Promise.all` to run\nthem concurrently and await the lot.\n",{"id":221,"difficulty":88,"q":222,"a":223},"callback-third-arg","What is the third argument passed to array iteration callbacks?","It's the **array being iterated** itself. It lets a callback reference\nneighboring elements without closing over an outer variable.\n\n```js\n[10, 20, 30].map((val, i, arr) =>\n  i > 0 ? val - arr[i - 1] : 0\n) \u002F\u002F [0, 10, 10] — differences\n```\n\nIt's rarely needed, but handy for look-ahead\u002Flook-behind logic and for writing\ngeneric helpers that don't depend on an external reference to the array.\n",null,{"description":86},"JavaScript array method interview questions — map, filter, reduce, forEach, some, every, find, flat, flatMap, Array.from and how to chain iteration methods effectively.","javascript\u002Farrays\u002Farray-methods","2026-06-18","Elw--T-gcVD4zuO2afQStkL-UYCKrtemiCrb2WELzjs",{"id":231,"title":232,"body":233,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":237,"navigation":91,"order":47,"path":238,"questions":239,"related":224,"seo":364,"seoDescription":365,"stem":366,"subtopic":367,"topic":64,"topicSlug":66,"updated":228,"__hash__":368},"qa\u002Fjavascript\u002Farrays\u002Fdestructuring-spread.md","Destructuring Spread",{"type":83,"value":234,"toc":235},[],{"title":86,"searchDepth":29,"depth":29,"links":236},[],{},"\u002Fjavascript\u002Farrays\u002Fdestructuring-spread",[240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,304,308,312,316,320,324,328,332,336,340,344,348,352,356,360],{"id":241,"difficulty":96,"q":242,"a":243},"array-destructuring-basics","What is array destructuring?","**Array destructuring** unpacks values from an array into distinct\nvariables by **position**, using a pattern on the left of `=`.\n\n```js\nconst [first, second] = [10, 20]\nfirst   \u002F\u002F 10\nsecond  \u002F\u002F 20  assigned by index, not name\n```\n\nIt works on any iterable, not just arrays — strings, Sets, Maps, and\ngenerators all destructure positionally.\n",{"id":245,"difficulty":96,"q":246,"a":247},"skipping-elements","How do you skip elements while destructuring?","Leave an **empty slot** (just a comma) for each element you want to skip.\n\n```js\nconst [, , third] = ['a', 'b', 'c']\nthird   \u002F\u002F 'c'  first two skipped\n```\n\nEach comma consumes one position. It's readable for one skip; for several,\nconsider naming with an underscore convention or indexing directly to keep\nit clear.\n",{"id":249,"difficulty":96,"q":250,"a":251},"default-values","How do default values work in array destructuring?","A default applies only when the matched value is **`undefined`** (not for\n`null` or other falsy values).\n\n```js\nconst [a = 1, b = 2] = [10]\na  \u002F\u002F 10\nb  \u002F\u002F 2   undefined -> default\n\nconst [c = 5] = [null]\nc  \u002F\u002F null  null is not undefined, no default\n```\n\nMissing array positions read as `undefined`, which is exactly why defaults\nkick in there.\n",{"id":253,"difficulty":96,"q":254,"a":255},"swapping-variables","How do you swap two variables with destructuring?","Build an array literal on the right and destructure it on the left — no\ntemp variable needed.\n\n```js\nlet a = 1, b = 2\n[a, b] = [b, a]\na  \u002F\u002F 2\nb  \u002F\u002F 1\n```\n\nThe right side is fully evaluated before assignment, so the swap is\natomic. Watch out: if the previous line lacks a semicolon, the leading\n`[` can be parsed as indexing — start the line with a semicolon if unsure.\n",{"id":257,"difficulty":88,"q":258,"a":259},"nested-destructuring","How do you destructure nested arrays?","Mirror the structure with nested patterns.\n\n```js\nconst [[a, b], [c]] = [[1, 2], [3]]\na  \u002F\u002F 1\nb  \u002F\u002F 2\nc  \u002F\u002F 3\n```\n\nYou can mix in defaults and skips at any level. Deeply nested patterns get\nhard to read fast — destructure one level and name intermediates if it\nstops being obvious.\n",{"id":261,"difficulty":88,"q":262,"a":263},"rest-element","What is the rest element in array destructuring?","A trailing **`...name`** collects all remaining elements into a **new\narray**.\n\n```js\nconst [head, ...tail] = [1, 2, 3, 4]\nhead  \u002F\u002F 1\ntail  \u002F\u002F [2, 3, 4]  a real array\n```\n\nThe rest element must be **last** — `const [...rest, last]` is a\nSyntaxError. It always produces an array, even if empty.\n",{"id":265,"difficulty":88,"q":266,"a":267},"rest-vs-spread","What's the difference between rest and spread, since both use ...?","Same syntax, opposite jobs. **Rest** *collects* multiple elements into one\narray (on the left, in a pattern). **Spread** *expands* one iterable into\nmultiple elements (on the right, in a literal or call).\n\n```js\nconst [first, ...rest] = arr      \u002F\u002F rest: gather\nconst copy = [...arr]             \u002F\u002F spread: expand\n```\n\nPosition is the tell: `...` on the binding side = rest; `...` on the value\nside = spread.\n",{"id":269,"difficulty":96,"q":270,"a":271},"spread-copy","How do you copy an array with spread, and what kind of copy is it?","`[...arr]` produces a **shallow copy** — a new top-level array whose\nelements are the same references.\n\n```js\nconst a = [{ x: 1 }, 2]\nconst b = [...a]\nb === a       \u002F\u002F false  new array\nb[0] === a[0] \u002F\u002F true   inner object still shared\n```\n\nFor nested data you need a deep copy: `structuredClone(a)`.\n",{"id":273,"difficulty":96,"q":274,"a":275},"spread-merge","How do you concatenate arrays with spread?","Spread each array into a new literal, in the order you want.\n\n```js\nconst merged = [...a, ...b, ...c]   \u002F\u002F flat concatenation\nconst withExtras = [0, ...a, 99]    \u002F\u002F insert around them\n```\n\nIt reads more clearly than `a.concat(b, c)` and lets you interleave\nindividual elements, though `concat` can be marginally faster for very\nlarge arrays.\n",{"id":277,"difficulty":88,"q":278,"a":279},"spread-vs-concat","When would you use concat instead of spread?","Functionally similar for merging, but **`concat`** has two edge behaviors\nspread doesn't: it can append non-array values directly, and it's often\nfaster for huge arrays since the engine doesn't iterate element-by-element.\n\n```js\n[1, 2].concat(3, [4, 5])   \u002F\u002F [1, 2, 3, 4, 5]  mixes values and arrays\n[...[1,2], 3, ...[4,5]]    \u002F\u002F same result via spread\n```\n\nUse spread for readability and interleaving; reach for `concat` in hot\npaths over large arrays.\n",{"id":281,"difficulty":88,"q":282,"a":283},"spread-iterables","What can you spread besides arrays?","Anything **iterable**: strings, `Set`, `Map`, `arguments`, NodeLists,\ngenerators.\n\n```js\n[...'abc']            \u002F\u002F ['a', 'b', 'c']  string -> chars\n[...new Set([1,1,2])] \u002F\u002F [1, 2]\n[...map.entries()]    \u002F\u002F [[k, v], ...]\n```\n\nPlain objects are **not** iterable, so `[...{a:1}]` throws. Use\n`Object.values`\u002F`entries` to turn an object into an iterable first.\n",{"id":285,"difficulty":88,"q":286,"a":287},"spread-string-chars","Why is [...str] safer than str.split('') for splitting characters?","Spread iterates by **code point** (respecting surrogate pairs), while\n`split('')` splits by UTF-16 **code unit**, breaking emoji and other\nastral characters.\n\n```js\n[...'a😀b']          \u002F\u002F ['a', '😀', 'b']  ✅\n'a😀b'.split('')     \u002F\u002F ['a', '\\ud83d', '\\ude00', 'b']  ❌ broken\n```\n\nPrefer spread (or `Array.from`) whenever input might contain non-BMP\ncharacters.\n",{"id":289,"difficulty":96,"q":290,"a":291},"spread-function-args","How do you pass an array as separate arguments?","Spread it in the call site — it replaces the old `Function.prototype.apply`\npattern.\n\n```js\nconst nums = [5, 1, 9]\nMath.max(...nums)        \u002F\u002F 9\nMath.max.apply(null, nums) \u002F\u002F old way\n```\n\nYou can also mix fixed and spread args: `fn(a, ...rest, b)`. One caveat:\nspreading a very large array (100k+) can hit argument-count limits — loop\nor `reduce` instead.\n",{"id":293,"difficulty":88,"q":294,"a":295},"rest-parameters-vs-destructuring","How does a rest element differ from rest parameters?","They look identical but live in different places. A **rest element**\nappears in a destructuring pattern and gathers leftover array items; **rest\nparameters** appear in a function signature and gather leftover arguments.\n\n```js\nconst [a, ...rest] = arr            \u002F\u002F rest element\nfunction f(first, ...others) {}     \u002F\u002F rest parameters\n```\n\nBoth produce real arrays (unlike the old `arguments` object), and both must\nbe last.\n",{"id":297,"difficulty":88,"q":298,"a":299},"destructure-in-params","How do you destructure an array in a function parameter?","Put the pattern directly in the parameter list — handy for functions\nreceiving coordinate pairs or `Object.entries` items.\n\n```js\nfunction dist([x1, y1], [x2, y2]) {\n  return Math.hypot(x2 - x1, y2 - y1)\n}\ndist([0, 0], [3, 4])   \u002F\u002F 5\n```\n\nAdd a default for the whole parameter (`= []`) if it might be missing,\notherwise destructuring `undefined` throws.\n",{"id":301,"difficulty":88,"q":302,"a":303},"destructure-in-loops","How is array destructuring used in for...of loops?","Destructure each iterated item inline — extremely common with\n`entries()` and `Object.entries`.\n\n```js\nfor (const [i, value] of arr.entries()) {\n  console.log(i, value)   \u002F\u002F index and value\n}\nfor (const [key, val] of Object.entries(obj)) { \u002F* ... *\u002F }\n```\n\nIt keeps the loop body clean versus indexing into a pair with `[0]`\u002F`[1]`.\n",{"id":305,"difficulty":88,"q":306,"a":307},"swap-array-elements","How do you swap two elements within an array?","Destructure the two positions on the left and provide them swapped on the\nright.\n\n```js\nconst a = [1, 2, 3, 4]\n;[a[1], a[3]] = [a[3], a[1]]\na   \u002F\u002F [1, 4, 3, 2]\n```\n\nAs with variable swaps, lead with a semicolon when the previous statement\ndoesn't end in one, so `[` isn't read as indexing.\n",{"id":309,"difficulty":161,"q":310,"a":311},"default-from-other","Can a destructuring default reference an earlier bound variable?","Yes — defaults are evaluated **left to right**, so a later default can use\nan already-assigned earlier one.\n\n```js\nconst [a = 1, b = a * 2] = []\na  \u002F\u002F 1\nb  \u002F\u002F 2   b's default used a\n```\n\nReferencing a variable that hasn't been bound *yet* (to its right) throws a\ntemporal-dead-zone error. Keep dependencies left-to-right.\n",{"id":313,"difficulty":88,"q":314,"a":315},"destructure-undefined","What happens when you destructure null or undefined?","Both throw a **TypeError**, because destructuring tries to read the\niterator (`Symbol.iterator`) off the value.\n\n```js\nconst [a] = null        \u002F\u002F TypeError\nconst [b] = undefined   \u002F\u002F TypeError\nconst [c] = []          \u002F\u002F c is undefined (empty but iterable)\n```\n\nGuard with a default at the source: `const [c] = maybeArr ?? []`.\n",{"id":317,"difficulty":161,"q":318,"a":319},"spread-shallow-pitfall","What's the classic bug with spreading nested arrays?","People assume `[...arr]` deep-copies, but inner arrays\u002Fobjects stay shared,\nso mutating them mutates the \"copy\" too.\n\n```js\nconst matrix = [[1], [2]]\nconst copy = [...matrix]\ncopy[0].push(99)\nmatrix[0]   \u002F\u002F [1, 99]  original changed\n```\n\nFor grids\u002Fnested structures use `matrix.map(row => [...row])` (one level)\nor `structuredClone(matrix)` (any depth).\n",{"id":321,"difficulty":88,"q":322,"a":323},"array-from-vs-spread","When is Array.from better than spread?","`Array.from` accepts a **mapping function** and works on **array-like**\nobjects (those with `length` but no `Symbol.iterator`), which spread can't\nhandle.\n\n```js\nArray.from({ length: 3 }, (_, i) => i)  \u002F\u002F [0, 1, 2]  array-like + map\n[...{ length: 3 }]                       \u002F\u002F TypeError, not iterable\n```\n\nUse spread for iterables and brevity; use `Array.from` for array-likes or\nwhen you want to map during creation.\n",{"id":325,"difficulty":88,"q":326,"a":327},"clone-and-modify","How do you immutably add or remove an item using spread?","Build a new array around the change instead of mutating.\n\n```js\nconst added   = [...arr, item]                 \u002F\u002F append\nconst prepend = [item, ...arr]                 \u002F\u002F prepend\nconst removed = [...arr.slice(0, i), ...arr.slice(i + 1)]  \u002F\u002F remove at i\n```\n\nThis is the standard pattern for React\u002FRedux state. The ES2023\n`arr.with(i, val)` and `toSpliced` cover replace\u002Fremove even more cleanly.\n",{"id":329,"difficulty":88,"q":330,"a":331},"spread-order-matters","Does the order of spread elements matter?","Yes — elements land in source order, so later items can override or follow\nearlier ones.\n\n```js\n[...a, ...b]   \u002F\u002F a's items first, then b's\n[...b, ...a]   \u002F\u002F reversed grouping\n```\n\nUnlike object spread (where later keys win), array spread doesn't\n\"override\" — every element is kept; only the resulting positions differ.\n",{"id":333,"difficulty":161,"q":334,"a":335},"nested-default-skip-combo","Can you combine skipping, defaults, and rest in one pattern?","Yes — they compose freely, as long as rest stays last.\n\n```js\nconst [, second = 0, ...rest] = [1]\nsecond  \u002F\u002F 0     (skipped first, defaulted missing second)\nrest    \u002F\u002F []    nothing left\n```\n\nPowerful but easy to over-pack; if a single pattern needs all three, it's\noften clearer to split into a couple of statements.\n",{"id":337,"difficulty":96,"q":338,"a":339},"destructure-return-values","How is array destructuring used to return multiple values?","A function returns an array (or tuple-like) and the caller destructures it\npositionally — the pattern behind React's `useState`.\n\n```js\nfunction minMax(arr) {\n  return [Math.min(...arr), Math.max(...arr)]\n}\nconst [lo, hi] = minMax([3, 1, 9])   \u002F\u002F lo=1, hi=9\n```\n\nUse array returns when order is meaningful and stable; prefer an object\nreturn when callers should pick fields by name.\n",{"id":341,"difficulty":96,"q":342,"a":343},"spread-set-dedupe","How do you dedupe an array with spread and a Set?","Wrap in a `Set` (drops duplicates by SameValueZero), then spread back to an\narray.\n\n```js\nconst unique = [...new Set([1, 1, 2, 3, 3])]  \u002F\u002F [1, 2, 3]\n```\n\nIt preserves first-seen order and is the idiomatic one-liner. Note it\ndedupes by reference for objects, so identical-looking objects won't\ncollapse.\n",{"id":345,"difficulty":88,"q":346,"a":347},"flatten-with-spread","Can you flatten an array of arrays with spread?","For a known, small number of arrays, yes. For an arbitrary array of\narrays, prefer **`flat`** or `reduce`.\n\n```js\n[...a, ...b]                 \u002F\u002F fine for a fixed set\n[[1],[2],[3]].flat()         \u002F\u002F [1, 2, 3]  arbitrary length\nrows.reduce((acc, r) => [...acc, ...r], [])  \u002F\u002F works but O(n²)\n```\n\nThe `reduce`-with-spread version reallocates each step — use `flat()` or\n`acc.push(...r)` for performance.\n",{"id":349,"difficulty":96,"q":350,"a":351},"spread-max-min","How do you find the max or min of an array?","Spread the array into `Math.max`\u002F`Math.min`.\n\n```js\nMath.max(...[3, 9, 1])  \u002F\u002F 9\nMath.min(...[3, 9, 1])  \u002F\u002F 1\n```\n\nCaveat: `Math.max()` of an **empty** array is `-Infinity` (and `min` is\n`Infinity`), and spreading a massive array may exceed argument limits — use\n`reduce` for those cases.\n",{"id":353,"difficulty":96,"q":354,"a":355},"ignore-with-underscore","How do you conventionally ignore destructured values you don't need?","Either skip with an empty slot, or bind to a throwaway name like `_`.\n\n```js\nconst [, , third] = list       \u002F\u002F skip slots\nconst [_a, _b, third2] = list  \u002F\u002F name-but-ignore convention\n```\n\nThe underscore is just a normal variable (linters often allow an `_`\nprefix to mean \"unused\"). Skipping slots avoids creating bindings at all.\n",{"id":357,"difficulty":161,"q":358,"a":359},"destructure-generator","What happens when you destructure a generator or infinite iterable?","Destructuring pulls only as many values as the pattern needs and then\nstops — so it works on **infinite** iterables.\n\n```js\nfunction* naturals() { let n = 1; while (true) yield n++ }\nconst [a, b, c] = naturals()\na, b, c   \u002F\u002F 1, 2, 3   only three pulled\n```\n\nBut a **rest element** (`const [first, ...rest]`) would try to drain the\nwhole iterable and hang forever — never use rest on an infinite source.\n",{"id":361,"difficulty":161,"q":362,"a":363},"swap-without-temp-perf","Is destructuring swap as fast as a temp variable?","Functionally identical; performance is essentially the same in modern\nengines, though a destructuring swap allocates a small array literal that\nthe optimizer usually elides.\n\n```js\n[a, b] = [b, a]          \u002F\u002F readable, idiomatic\nconst t = a; a = b; b = t \u002F\u002F traditional, zero allocation\n```\n\nPrefer the destructuring form for clarity; only the traditional swap in\nextremely hot numeric loops where you've profiled an actual difference.\n",{"description":86},"JavaScript array destructuring and spread interview questions — defaults, skipping, swapping, nested patterns, rest elements, copying and merging arrays, spread vs concat and consuming iterables.","javascript\u002Farrays\u002Fdestructuring-spread","Array Destructuring & Spread","dwUK35g8bIJziTXcSu72Y0e_b_MJftZi1sERh1noiQ0",{"id":370,"title":371,"body":372,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":376,"navigation":91,"order":29,"path":377,"questions":378,"related":224,"seo":503,"seoDescription":504,"stem":505,"subtopic":506,"topic":64,"topicSlug":66,"updated":228,"__hash__":507},"qa\u002Fjavascript\u002Farrays\u002Fmutating-vs-nonmutating.md","Mutating Vs Nonmutating",{"type":83,"value":373,"toc":374},[],{"title":86,"searchDepth":29,"depth":29,"links":375},[],{},"\u002Fjavascript\u002Farrays\u002Fmutating-vs-nonmutating",[379,383,387,391,395,399,403,407,411,415,419,423,427,431,435,439,443,447,451,455,459,463,467,471,475,479,483,487,491,495,499],{"id":380,"difficulty":96,"q":381,"a":382},"what-is-mutation","What does it mean for an array method to mutate the array?","A **mutating** method changes the **original array in place** rather than\nreturning a fresh copy. The variable still points to the same array, but its\ncontents have changed.\n\n```js\nconst arr = [1, 2, 3]\narr.push(4) \u002F\u002F mutates: arr is now [1, 2, 3, 4]\n```\n\nThis matters because other code holding a reference to the same array sees the\nchange too — a frequent source of surprising bugs in shared state.\n",{"id":384,"difficulty":88,"q":385,"a":386},"list-mutating","Which array methods mutate the original array?","The classic mutators all change the array in place:\n\n```text\npush, pop, shift, unshift  -> add\u002Fremove ends\nsplice                     -> insert\u002Fremove\u002Freplace anywhere\nsort, reverse              -> reorder\nfill, copyWithin           -> overwrite ranges\n```\n\nA memory aid: if a method changes **length or order**, it almost certainly\nmutates. The notable surprise is that **sort** and **reverse** mutate — many\nassume they return a new array like `map`.\n",{"id":388,"difficulty":88,"q":389,"a":390},"list-nonmutating","Which common array methods return a new array instead of mutating?","These leave the original untouched and return a **new array**:\n\n```text\nmap, filter, slice, concat, flat, flatMap\ntoSorted, toReversed, toSpliced, with   (ES2023)\n```\n\nPlus the spread copy `[...arr]`. As a rule, the **iteration\u002Ftransform** methods\nare non-mutating, while the **in-place edit** methods mutate. Knowing which is\nwhich is essential for writing predictable code.\n",{"id":392,"difficulty":96,"q":393,"a":394},"push-vs-concat","What is the difference between push and concat?","**push** mutates the array and returns the **new length**; **concat** returns a\n**new array** and leaves the original alone.\n\n```js\nconst a = [1, 2]\na.push(3)        \u002F\u002F a is [1,2,3], returns 3\nconst b = a.concat(4) \u002F\u002F b is [1,2,3,4], a unchanged\n```\n\nPitfall: people sometimes write `arr = arr.push(x)`, which sets `arr` to a\nnumber (the length). Use `concat` or spread when you want a new array\nreference.\n",{"id":396,"difficulty":88,"q":397,"a":398},"slice-vs-splice","What is the difference between slice and splice?","**slice** is **non-mutating**: it returns a shallow copy of a range. **splice**\n**mutates**: it removes\u002Finserts elements in place and returns the removed ones.\n\n```js\nconst arr = [1, 2, 3, 4]\narr.slice(1, 3)     \u002F\u002F [2, 3], arr unchanged\narr.splice(1, 2)    \u002F\u002F removes [2, 3], arr is now [1, 4]\n```\n\nThe names look alike but behave oppositely on mutation. Confusing them is a\nclassic bug — remember **slice = copy, splice = surgery**.\n",{"id":400,"difficulty":88,"q":401,"a":402},"sort-mutates","Does sort mutate the array?","Yes. **sort** sorts the array **in place** and also returns a reference to that\n**same** array — so both the original and the return value are sorted.\n\n```js\nconst arr = [3, 1, 2]\nconst sorted = arr.sort()\nsorted === arr \u002F\u002F true — same array\narr            \u002F\u002F [1, 2, 3] — original is changed\n```\n\nTo sort without mutating, copy first (`[...arr].sort()`) or use **toSorted()**\nin modern environments. The same applies to `reverse`.\n",{"id":404,"difficulty":88,"q":405,"a":406},"tosorted","What is toSorted and how does it differ from sort?","**toSorted** (ES2023) returns a **new sorted array** and leaves the original\nunchanged — the immutable counterpart of `sort`.\n\n```js\nconst arr = [3, 1, 2]\nconst sorted = arr.toSorted() \u002F\u002F [1, 2, 3]\narr                           \u002F\u002F [3, 1, 2] — untouched\n```\n\nIt takes the same optional comparator as `sort`. Use it to avoid the classic\n`[...arr].sort()` copy dance, especially in React state where mutating is a\nbug.\n",{"id":408,"difficulty":88,"q":409,"a":410},"toreversed-tospliced-with","What do toReversed, toSpliced, and with do?","They are the **immutable** versions of `reverse`, `splice`, and index\nassignment, all returning a **new array** (ES2023).\n\n```js\nconst arr = [1, 2, 3]\narr.toReversed()       \u002F\u002F [3, 2, 1], arr unchanged\narr.toSpliced(1, 1, 9) \u002F\u002F [1, 9, 3], arr unchanged\narr.with(0, 100)       \u002F\u002F [100, 2, 3], arr unchanged\n```\n\n`with(i, value)` is the immutable replacement for `arr[i] = value`. Together\nthese let you write update logic without copying first.\n",{"id":412,"difficulty":161,"q":413,"a":414},"why-mutation-bugs","Why does mutation cause bugs in shared state?","When two variables reference the **same array**, mutating through one changes\nwhat the other sees. Functions that mutate their arguments cause **action at a\ndistance**.\n\n```js\nconst original = [1, 2, 3]\nconst sorted = original\nsorted.sort((a, b) => b - a)\noriginal \u002F\u002F [3, 2, 1] — caller's array got reordered\n```\n\nFrameworks like React rely on **referential equality** to detect changes;\nmutating in place keeps the same reference, so the UI may not re-render.\nReturning new arrays avoids both classes of bug.\n",{"id":416,"difficulty":96,"q":417,"a":418},"copy-array-ways","What are the ways to copy an array?","For a **shallow** copy, any of these work:\n\n```js\nconst a = [1, 2, 3]\nconst b = [...a]        \u002F\u002F spread (most common)\nconst c = a.slice()     \u002F\u002F no args = full copy\nconst d = Array.from(a) \u002F\u002F\nconst e = a.concat()    \u002F\u002F\n```\n\nAll four copy the top level only. If the array holds objects, the copies share\nthose objects — see deep copying for nested data.\n",{"id":420,"difficulty":88,"q":421,"a":422},"shallow-vs-deep","What is the difference between a shallow and a deep copy of an array?","A **shallow** copy duplicates the array but shares the **same nested object\nreferences**. A **deep** copy duplicates everything recursively.\n\n```js\nconst arr = [{ n: 1 }]\nconst shallow = [...arr]\nshallow[0].n = 99\narr[0].n \u002F\u002F 99 — nested object is shared\n\nconst deep = structuredClone(arr)\ndeep[0].n = 1\narr[0].n \u002F\u002F 99 — independent\n```\n\nSpread\u002Fslice are shallow; reach for `structuredClone` when nested data must be\nindependent.\n",{"id":424,"difficulty":88,"q":425,"a":426},"structuredclone","When and how do you use structuredClone for arrays?","**structuredClone** does a true **deep copy** of arrays containing nested\nobjects, arrays, Maps, Sets, Dates, and more — without the limitations of\nJSON tricks.\n\n```js\nconst data = [{ id: 1, tags: ['a'] }]\nconst copy = structuredClone(data) \u002F\u002F fully independent\n```\n\nCaveat: it **cannot clone functions, DOM nodes, or class instances** with\nmethods (it throws or drops the prototype). It's built into modern Node and all\ncurrent browsers.\n",{"id":428,"difficulty":88,"q":429,"a":430},"json-deep-copy","What are the pitfalls of JSON.parse(JSON.stringify(arr)) for deep copy?","It deep-copies plain data but **silently corrupts** anything non-JSON:\n\n```js\nconst arr = [{ d: new Date(), fn: () => {}, u: undefined, n: NaN }]\nJSON.parse(JSON.stringify(arr))\n\u002F\u002F Date -> string, fn -> dropped, undefined -> dropped, NaN -> null\n```\n\nIt also throws on **circular references**. Prefer `structuredClone` for deep\ncopies; reserve the JSON trick for arrays of plain, JSON-safe values where the\nconversions don't matter.\n",{"id":432,"difficulty":88,"q":433,"a":434},"immutable-add","How do you add an item to an array immutably?","Build a **new array** with spread instead of `push`\u002F`unshift`:\n\n```js\nconst arr = [1, 2, 3]\nconst appended = [...arr, 4]   \u002F\u002F add to end\nconst prepended = [0, ...arr]  \u002F\u002F add to start\narr \u002F\u002F [1, 2, 3] — unchanged\n```\n\nThis pattern is standard in Redux reducers and React `setState`, where mutating\nthe existing array would break change detection and time-travel debugging.\n",{"id":436,"difficulty":88,"q":437,"a":438},"immutable-remove","How do you remove an item from an array immutably?","Use **filter** (by value\u002Fpredicate) or **slice + spread** (by index) to produce\na new array.\n\n```js\nconst arr = [1, 2, 3, 4]\narr.filter(n => n !== 3)             \u002F\u002F [1, 2, 4] by value\nconst i = 2\n[...arr.slice(0, i), ...arr.slice(i + 1)] \u002F\u002F [1, 2, 4] by index\narr.toSpliced(i, 1)                  \u002F\u002F [1, 2, 4] ES2023\n```\n\nAvoid `splice`, which mutates. `toSpliced` is the cleanest modern option for\nindex-based removal.\n",{"id":440,"difficulty":88,"q":441,"a":442},"immutable-update","How do you update an item at an index immutably?","Use **map** with the index, or **with()** in modern environments — never\n`arr[i] = x`, which mutates.\n\n```js\nconst arr = [1, 2, 3]\narr.map((v, idx) => (idx === 1 ? 99 : v)) \u002F\u002F [1, 99, 3]\narr.with(1, 99)                            \u002F\u002F [1, 99, 3] ES2023\narr \u002F\u002F [1, 2, 3] — unchanged\n```\n\nFor arrays of objects, also spread the object: `arr.map(o => o.id === id ? {\n...o, done: true } : o)` to avoid mutating the nested object.\n",{"id":444,"difficulty":161,"q":445,"a":446},"freeze-array","Does Object.freeze make an array fully immutable?","It makes it **shallowly** immutable: you can't add, remove, or reassign\ntop-level elements, but **nested objects stay mutable**.\n\n```js\nconst arr = Object.freeze([{ n: 1 }])\narr.push(2)   \u002F\u002F throws in strict mode (or silently fails)\narr[0].n = 99 \u002F\u002F still works — nested object not frozen\n```\n\nFor deep immutability you must freeze recursively (a \"deep freeze\"). Also note\nmutating methods like `push` throw on a frozen array in strict mode.\n",{"id":448,"difficulty":88,"q":449,"a":450},"fill","What does fill do and does it mutate?","**fill** overwrites a range of the array with a static value **in place** — it\nmutates and returns the same array.\n\n```js\nconst arr = [1, 2, 3, 4]\narr.fill(0, 1, 3) \u002F\u002F [1, 0, 0, 4], arr mutated\nnew Array(3).fill(0) \u002F\u002F [0, 0, 0] — common init pattern\n```\n\nGotcha: filling with a **shared object** puts the **same reference** in every\nslot: `new Array(3).fill([])` gives three references to one array. Use\n`Array.from({length:3}, () => [])` for distinct objects.\n",{"id":452,"difficulty":161,"q":453,"a":454},"copywithin","What does copyWithin do?","**copyWithin(target, start, end)** copies a slice of the array to another\nposition **within the same array**, in place, without changing its length.\n\n```js\nconst arr = [1, 2, 3, 4, 5]\narr.copyWithin(0, 3) \u002F\u002F [4, 5, 3, 4, 5] — copy from index 3 to 0\n```\n\nIt mutates and is rarely used in app code — it exists mainly for high\nperformance buffer manipulation. Worth recognizing in interviews but seldom\nreached for in practice.\n",{"id":456,"difficulty":96,"q":457,"a":458},"reverse-mutates","Does reverse mutate the array?","Yes — **reverse** reverses the array **in place** and returns a reference to the\nsame array.\n\n```js\nconst arr = [1, 2, 3]\narr.reverse()\narr \u002F\u002F [3, 2, 1] — original changed\n```\n\nTo reverse without mutating, use `[...arr].reverse()` or **toReversed()**. This\nmutation surprises people who expect array methods to be functional like `map`.\n",{"id":460,"difficulty":96,"q":461,"a":462},"assignment-not-copy","Why doesn't const b = a create a copy of the array?","Arrays are **reference types**. Assignment copies the **reference**, not the\ndata, so both names point at the **same array**.\n\n```js\nconst a = [1, 2, 3]\nconst b = a\nb.push(4)\na \u002F\u002F [1, 2, 3, 4] — same array\n```\n\nTo get an independent array you must explicitly copy: `const b = [...a]`. This\nreference behavior underlies most accidental-mutation bugs.\n",{"id":464,"difficulty":88,"q":465,"a":466},"mutation-in-functions","How can passing an array to a function mutate the caller's array?","The function receives the **same reference**, so any mutating method affects the\ncaller's array.\n\n```js\nfunction addItem(arr) { arr.push('x') } \u002F\u002F mutates caller\nconst list = [1]\naddItem(list)\nlist \u002F\u002F [1, 'x']\n```\n\nWrite **pure** functions that return new arrays instead: `function addItem(arr)\n{ return [...arr, 'x'] }`. This keeps call sites free of surprises and makes the\ncode easier to test.\n",{"id":468,"difficulty":88,"q":469,"a":470},"spread-shallow","Is the spread operator a deep or shallow copy for arrays?","**Shallow.** Spread copies the top-level elements; nested objects\u002Farrays are\nstill **shared by reference**.\n\n```js\nconst arr = [[1], [2]]\nconst copy = [...arr]\ncopy[0].push(99)\narr[0] \u002F\u002F [1, 99] — inner array shared\n```\n\nFor nested data you need a deep copy (`structuredClone`) or to spread each\nlevel. Treat spread as a fast top-level clone, nothing more.\n",{"id":472,"difficulty":161,"q":473,"a":474},"react-mutation","Why must you avoid mutating arrays in React state?","React decides whether to re-render by comparing the **previous and next\nreference**. Mutating in place keeps the **same reference**, so React thinks\nnothing changed.\n\n```js\n\u002F\u002F mutation — same reference, no re-render\nitems.push(newItem); setItems(items)\n\u002F\u002F new reference — triggers re-render\nsetItems([...items, newItem])\n```\n\nAlways create a new array (`map`, `filter`, spread, `toSorted`, `with`) when\nupdating state so React sees the change.\n",{"id":476,"difficulty":88,"q":477,"a":478},"empty-array-length","How does setting arr.length mutate the array?","Assigning to **length** mutates in place: shrinking truncates elements,\ngrowing pads with empty slots, and `length = 0` empties the array.\n\n```js\nconst arr = [1, 2, 3, 4]\narr.length = 2 \u002F\u002F [1, 2] — truncated\narr.length = 0 \u002F\u002F [] — cleared\n```\n\n`arr.length = 0` is a fast in-place clear that affects every reference to the\narray. To clear without mutating shared references, reassign: `arr = []`.\n",{"id":480,"difficulty":96,"q":481,"a":482},"pop-shift-return","What do pop and shift return, and do they mutate?","Both **mutate** and return the **removed element**. `pop` removes from the end,\n`shift` from the start.\n\n```js\nconst arr = [1, 2, 3]\narr.pop()   \u002F\u002F returns 3, arr is [1, 2]\narr.shift() \u002F\u002F returns 1, arr is [2]\n```\n\nNote `shift`\u002F`unshift` are **O(n)** because every remaining element must be\nreindexed, whereas `push`\u002F`pop` are O(1). Prefer end operations in hot loops.\n",{"id":484,"difficulty":96,"q":485,"a":486},"concat-vs-spread","Are concat and spread interchangeable for combining arrays?","Mostly yes — both return a **new array** without mutating. Spread reads more\nnaturally; `concat` has one nicety: it accepts **non-array values** directly.\n\n```js\n[...a, ...b]      \u002F\u002F merge two arrays\na.concat(b)       \u002F\u002F same result\na.concat(b, 5, 6) \u002F\u002F concat flattens array args and appends values\n[...a, b]         \u002F\u002F pushes the array b as a single element\n```\n\nFor huge arrays `concat` can be marginally faster, but readability usually\nfavors spread.\n",{"id":488,"difficulty":161,"q":489,"a":490},"in-place-dedupe","How do you dedupe an array, mutating versus non-mutating?","The clean, **non-mutating** way uses a `Set`:\n\n```js\nconst unique = [...new Set(arr)] \u002F\u002F new array, order preserved\n```\n\nAn in-place dedupe is fiddly and error-prone (you'd `splice` while iterating,\nwhich shifts indices). Prefer the Set approach. Note it uses **SameValueZero**,\nso `NaN` is deduped correctly but distinct objects with equal contents are not.\n",{"id":492,"difficulty":88,"q":493,"a":494},"immutability-libraries","What problem do libraries like Immer solve for arrays?","They let you write **mutating-looking** code that actually produces a **new,\nimmutable** array under the hood, avoiding verbose spread chains for deeply\nnested updates.\n\n```js\nconst next = produce(state, draft => {\n  draft.items.push(newItem) \u002F\u002F looks like mutation\n}) \u002F\u002F state is untouched, next is a new tree\n```\n\nImmer tracks changes to a proxy \"draft\" and builds the new structure for you.\nIt's popular in Redux Toolkit precisely because deep immutable updates with\nspread get unwieldy.\n",{"id":496,"difficulty":161,"q":497,"a":498},"detect-mutation","How can you guard against accidental mutation during development?","Use **Object.freeze** in development to make accidental mutation throw, lean on\n**const** (which prevents reassignment, not mutation), and adopt lint rules or\nlibraries that enforce immutability.\n\n```js\nconst config = Object.freeze([1, 2, 3])\nconfig.push(4) \u002F\u002F throws in strict mode — caught early\n```\n\nIn TypeScript, `readonly` arrays and `as const` give **compile-time**\nprotection with zero runtime cost, catching mutation before it ships.\n",{"id":500,"difficulty":88,"q":501,"a":502},"prefer-immutable","When should you prefer immutable updates over mutation?","Prefer **immutable** updates whenever the array is **shared** — across\ncomponents, stored in framework state, or passed between modules — because new\nreferences make change tracking and reasoning reliable.\n\n```js\n\u002F\u002F shared state -> immutable\nsetItems(items.filter(i => i.id !== id)) \u002F\u002F\n```\n\n**Mutation is fine** for short-lived local arrays you fully own inside a\nfunction, where in-place edits are faster and no one else can observe them.\n",{"description":86},"JavaScript array mutation interview questions — which methods mutate versus return a new array, immutability patterns, copying arrays, the new toSorted and with methods, and structuredClone for nested data.","javascript\u002Farrays\u002Fmutating-vs-nonmutating","Mutating vs Non-Mutating","54QuTuRi8ysB-Ri5IyNJ6VfxTJXeWyfqI2yjBC5sMQg",{"id":509,"title":510,"body":511,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":515,"navigation":91,"order":38,"path":516,"questions":517,"related":224,"seo":638,"seoDescription":639,"stem":640,"subtopic":641,"topic":64,"topicSlug":66,"updated":228,"__hash__":642},"qa\u002Fjavascript\u002Farrays\u002Fsearching-sorting.md","Searching Sorting",{"type":83,"value":512,"toc":513},[],{"title":86,"searchDepth":29,"depth":29,"links":514},[],{},"\u002Fjavascript\u002Farrays\u002Fsearching-sorting",[518,522,526,530,534,538,542,544,548,552,556,559,563,567,571,575,579,582,586,590,594,598,602,606,610,614,618,622,626,630,634],{"id":519,"difficulty":96,"q":520,"a":521},"indexof-basics","How does indexOf work and what does it return when nothing is found?","**`indexOf`** returns the index of the first element strictly equal\n(`===`) to the search value, or **`-1`** if it is not present.\n\n```js\nconst a = ['x', 'y', 'z']\na.indexOf('y')   \u002F\u002F 1\na.indexOf('q')   \u002F\u002F -1  the \"not found\" sentinel\n```\n\nThe classic pitfall is treating `-1` as falsy: `if (a.indexOf(x))` is\n**wrong** because index `0` is also falsy. Compare explicitly with\n`!== -1`, or prefer `includes` when you only need a boolean.\n",{"id":523,"difficulty":96,"q":524,"a":525},"lastindexof","What is the difference between indexOf and lastIndexOf?","**`indexOf`** searches front-to-back and returns the first match;\n**`lastIndexOf`** searches back-to-front and returns the last match.\nBoth use `===` and return `-1` when absent.\n\n```js\nconst a = [1, 2, 3, 2, 1]\na.indexOf(2)      \u002F\u002F 1\na.lastIndexOf(2)  \u002F\u002F 3  last occurrence\n```\n\nEach also takes an optional start index. A subtle point: for\n`lastIndexOf` the second argument is where to *begin searching\nbackwards*, so `a.lastIndexOf(2, 2)` searches indices 2->0.\n",{"id":527,"difficulty":88,"q":528,"a":529},"includes-vs-indexof","When should you use includes instead of indexOf?","Use **`includes`** when you only care *whether* a value exists — it\nreturns a boolean and reads clearly. Use **`indexOf`** when you need the\n*position*.\n\n```js\nif (tags.includes('urgent')) { \u002F* ... *\u002F }   \u002F\u002F clear intent\nconst at = tags.indexOf('urgent')            \u002F\u002F when you need where\n```\n\nThe other reason to prefer `includes`: it finds `NaN`, which `indexOf`\ncannot (see the next question).\n",{"id":531,"difficulty":88,"q":532,"a":533},"nan-search-gotcha","Why can't indexOf find NaN, but includes can?","`indexOf` compares with `===`, and `NaN === NaN` is **false** — so it can\nnever match. `includes` uses the **SameValueZero** algorithm, which\ntreats `NaN` as equal to `NaN`.\n\n```js\n[NaN].indexOf(NaN)    \u002F\u002F -1  can't find it\n[NaN].includes(NaN)   \u002F\u002F true\n```\n\nSameValueZero is also why `includes(0)` matches both `+0` and `-0`. If\nyou must locate a `NaN` index, use `findIndex(Number.isNaN)`.\n",{"id":535,"difficulty":96,"q":536,"a":537},"find-vs-filter","What is the difference between find and filter?","**`find`** returns the **first element** that satisfies the predicate (or\n`undefined`); **`filter`** returns a **new array** of *all* matches.\n\n```js\nusers.find(u => u.id === 7)     \u002F\u002F the one user, or undefined\nusers.filter(u => u.active)     \u002F\u002F array of every active user\n```\n\nUse `find` for \"give me the one I want\" — it also short-circuits on the\nfirst match, so it's cheaper than `filter()[0]` which scans the whole\narray.\n",{"id":539,"difficulty":96,"q":540,"a":541},"findindex","When would you use findIndex over indexOf?","**`indexOf`** searches by value equality; **`findIndex`** searches by a\n**predicate function**, so it works for objects and complex conditions.\n\n```js\nconst i = users.indexOf(someUser)          \u002F\u002F needs the exact reference\nconst j = users.findIndex(u => u.id === 7) \u002F\u002F search by a property\n```\n\nBoth return `-1` when nothing matches. Reach for `findIndex` whenever the\nmatch is \"the element where some condition holds\" rather than \"this exact\nvalue.\"\n",{"id":128,"difficulty":88,"q":129,"a":543},"They are the back-to-front counterparts of `find`\u002F`findIndex`: they walk\nthe array **from the end** and return the first matching element \u002F index.\n\n```js\nconst nums = [1, 8, 3, 9, 2]\nnums.findLast(n => n > 4)       \u002F\u002F 9  last match, not first\nnums.findLastIndex(n => n > 4)  \u002F\u002F 3\n```\n\nBefore these (ES2023) you'd reverse a copy or loop manually. They're handy\nfor \"most recent\" lookups in append-ordered data like logs.\n",{"id":545,"difficulty":96,"q":546,"a":547},"some-every-search","How do some and every help with searching?","**`some`** answers \"does *any* element match?\" and **`every`** answers\n\"do *all* elements match?\" — both return a boolean and short-circuit.\n\n```js\nnums.some(n => n \u003C 0)    \u002F\u002F true if there's at least one negative\nnums.every(n => n > 0)   \u002F\u002F true only if all are positive\n```\n\n`some` stops at the first `true`; `every` stops at the first `false`. A\ngotcha: `every` on an **empty array is `true`** (vacuous truth) and `some`\non an empty array is `false`.\n",{"id":549,"difficulty":88,"q":550,"a":551},"sort-default-gotcha","Why does sorting numbers with sort() give wrong results?","Without a comparator, **`sort` converts elements to strings** and compares\nthem by UTF-16 code unit — so numbers sort lexicographically.\n\n```js\n[10, 1, 2, 20].sort()            \u002F\u002F [1, 10, 2, 20]  \"10\" \u003C \"2\"\n[10, 1, 2, 20].sort((a,b)=>a-b)  \u002F\u002F [1, 2, 10, 20]\n```\n\nAlways pass a comparator for numbers. This string-coercion default trips\nup nearly everyone at least once.\n",{"id":553,"difficulty":96,"q":554,"a":555},"numeric-comparator","How do you write an ascending and descending numeric comparator?","A comparator returns a **negative** number if `a` should come first, a\n**positive** number if `b` should, and `0` to leave order unchanged.\n\n```js\narr.sort((a, b) => a - b)   \u002F\u002F ascending\narr.sort((a, b) => b - a)   \u002F\u002F descending\n```\n\nThe `a - b` trick works only for numbers. Don't return a boolean\n(`a > b`) — coerced to `0`\u002F`1` it never yields a negative, so the sort is\nbroken.\n",{"id":400,"difficulty":88,"q":557,"a":558},"Does sort() mutate the array? How do you sort without mutating?","Yes — **`sort` sorts in place and returns the same array reference**.\nThat can surprise callers sharing the array.\n\n```js\nconst a = [3, 1, 2]\nconst b = a.sort((x,y)=>x-y)\nb === a            \u002F\u002F true  original mutated\n\nconst sorted = [...a].sort((x,y)=>x-y)  \u002F\u002F copy first\nconst safe = a.toSorted((x,y)=>x-y)     \u002F\u002F ES2023, returns new array\n```\n\nPrefer `toSorted` (or spread-then-sort) in code that values immutability,\ne.g. React state.\n",{"id":560,"difficulty":161,"q":561,"a":562},"stable-sort","Is JavaScript's sort stable, and why does that matter?","Since ES2019 `sort` is guaranteed **stable**: elements the comparator\ntreats as equal keep their original relative order. This makes\n**multi-pass sorting** reliable.\n\n```js\n\u002F\u002F sort by name, then by age — age becomes the primary key,\n\u002F\u002F ties broken by the earlier name order\npeople.sort((a,b)=>a.name.localeCompare(b.name))\n      .sort((a,b)=>a.age - b.age)  \u002F\u002F stable keeps name order within an age\n```\n\nBefore ES2019, engines like V8 used an unstable sort for large arrays, so\nthis pattern wasn't portable.\n",{"id":564,"difficulty":88,"q":565,"a":566},"sort-objects","How do you sort an array of objects by a property?","Compare the property inside the comparator. Subtract for numbers, use\n`localeCompare` for strings.\n\n```js\nusers.sort((a, b) => a.age - b.age)              \u002F\u002F numeric field\nusers.sort((a, b) => a.name.localeCompare(b.name)) \u002F\u002F string field\n```\n\nDon't use `a.name > b.name` directly — it returns a boolean and breaks the\ncomparator contract. Remember it mutates, so copy first if needed.\n",{"id":568,"difficulty":161,"q":569,"a":570},"multi-key-sort","How do you sort by multiple keys?","Evaluate keys in priority order and return the first non-zero comparison.\n\n```js\npeople.sort((a, b) =>\n  a.lastName.localeCompare(b.lastName) ||  \u002F\u002F primary\n  a.firstName.localeCompare(b.firstName) || \u002F\u002F tiebreaker\n  a.age - b.age                             \u002F\u002F final tiebreaker\n)\n```\n\nThe `||` chain works because a `0` (equal) is falsy, so it falls through\nto the next key. Clean and avoids nested `if`s.\n",{"id":572,"difficulty":88,"q":573,"a":574},"localecompare","Why use localeCompare for sorting strings?","Comparing strings with `\u003C`\u002F`>` uses raw UTF-16 code units, which mishandles\naccents and locale rules. **`localeCompare`** sorts the way humans expect\nfor a given language.\n\n```js\n['é', 'a', 'z'].sort()                       \u002F\u002F ['a', 'z', 'é']\n['é', 'a', 'z'].sort((a,b)=>a.localeCompare(b)) \u002F\u002F ['a', 'é', 'z']\n```\n\nFor large arrays, build a reusable `Intl.Collator` and pass its `compare`\nmethod — it's much faster than calling `localeCompare` repeatedly.\n",{"id":576,"difficulty":88,"q":577,"a":578},"case-insensitive-sort","How do you sort strings case-insensitively?","Either lowercase both sides, or use `localeCompare` with the\n`sensitivity: 'base'` option (which also ignores accents).\n\n```js\narr.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))\n\u002F\u002F or\narr.sort((a, b) =>\n  a.localeCompare(b, undefined, { sensitivity: 'base' }))  \u002F\u002F\n```\n\nThe `Intl` option is preferable: lowercasing can be wrong for some\nlanguages (e.g. Turkish dotless İ).\n",{"id":456,"difficulty":96,"q":580,"a":581},"Does reverse() mutate, and what's the immutable alternative?","Yes — **`reverse` reverses in place** and returns the same array. The\nES2023 immutable version is **`toReversed`**.\n\n```js\nconst a = [1, 2, 3]\na.reverse()        \u002F\u002F a is now [3, 2, 1]  mutated\nconst b = a.toReversed()  \u002F\u002F new array, a untouched\n```\n\nTo reverse-sort numbers, you don't need `reverse` at all — just flip the\ncomparator: `sort((x,y)=>y-x)`.\n",{"id":583,"difficulty":88,"q":584,"a":585},"indexof-fromindex","How does the second argument to indexOf and includes work?","It's the **start index**. Searching begins there and continues to the end.\nNegative values count from the end.\n\n```js\nconst a = ['a', 'b', 'a', 'b']\na.indexOf('a', 1)    \u002F\u002F 2  (skips index 0)\na.includes('a', -1)  \u002F\u002F false (only looks at last element)\n```\n\nUseful for finding *all* occurrences in a loop: keep calling\n`indexOf(x, lastFound + 1)` until it returns `-1`.\n",{"id":587,"difficulty":161,"q":588,"a":589},"find-all-indices","How do you find all indices where a condition holds?","There's no built-in, but `reduce` collects them in one pass, or `map` +\n`filter`.\n\n```js\nconst evens = nums.reduce((acc, n, i) => {\n  if (n % 2 === 0) acc.push(i)\n  return acc\n}, [])  \u002F\u002F array of indices\n```\n\nAvoid the naive `nums.map((n,i)=> n%2===0 ? i : -1).filter(i=>i!==-1)` —\nit's two passes and the `-1` sentinel is fragile if `0` is a valid index.\n",{"id":591,"difficulty":161,"q":592,"a":593},"binary-search","When is a manual binary search worthwhile over includes\u002FindexOf?","`includes`\u002F`indexOf` are **O(n)** linear scans. If the array is **already\nsorted** and you search it many times, a **binary search** is O(log n).\n\n```js\nfunction bsearch(arr, target) {\n  let lo = 0, hi = arr.length - 1\n  while (lo \u003C= hi) {\n    const mid = (lo + hi) >> 1\n    if (arr[mid] === target) return mid\n    arr[mid] \u003C target ? (lo = mid + 1) : (hi = mid - 1)\n  }\n  return -1\n}\n```\n\nThe pitfall: the array **must** stay sorted, and `(lo+hi)>>1` assumes\nindices small enough to avoid overflow (fine in practice for arrays).\n",{"id":595,"difficulty":161,"q":596,"a":597},"sort-numbers-strings-mix","What happens if you sort an array with mixed types?","The default sort stringifies everything, giving surprising order; a numeric\ncomparator on mixed types produces `NaN` comparisons that leave order\neffectively undefined.\n\n```js\n[3, '1', 2].sort()              \u002F\u002F ['1', 2, 3] — all compared as strings\n[3, 'x', 2].sort((a,b)=>a-b)    \u002F\u002F 'x'-num is NaN, order unreliable\n```\n\nNormalize types before sorting (e.g. `Number(x)`), or filter out invalid\nentries first. Mixed-type arrays are usually a data-modeling smell.\n",{"id":599,"difficulty":161,"q":600,"a":601},"sort-undefined","How does sort handle undefined and holes?","`sort` moves all **`undefined`** values to the **end** without calling the\ncomparator on them, and **holes** in sparse arrays go after even those.\n\n```js\n[3, undefined, 1].sort((a,b)=>a-b)  \u002F\u002F [1, 3, undefined]\n```\n\nSo you can't reliably place `undefined` via a comparator — the engine\nhandles them specially. Strip or default them beforehand if you need\nspecific placement.\n",{"id":603,"difficulty":88,"q":604,"a":605},"includes-object-reference","Why does includes return false for an object that \"looks\" the same?","`includes` uses identity (SameValueZero), so two distinct objects with the\nsame contents are **not** equal.\n\n```js\nconst arr = [{ id: 1 }]\narr.includes({ id: 1 })           \u002F\u002F false different reference\narr.some(o => o.id === 1)         \u002F\u002F true  compare by value\n```\n\nFor \"contains an object like this,\" use `some`\u002F`find` with a predicate, not\n`includes`\u002F`indexOf`.\n",{"id":607,"difficulty":88,"q":608,"a":609},"tosorted-toreversed","What are toSorted, toReversed, toSpliced, and with?","They are ES2023 **non-mutating** versions of `sort`, `reverse`, `splice`,\nand bracket assignment — each returns a **new array**.\n\n```js\na.toSorted((x,y)=>x-y)   \u002F\u002F sorted copy\na.toReversed()           \u002F\u002F reversed copy\na.toSpliced(1, 2)        \u002F\u002F copy with items removed\u002Finserted\na.with(0, 'new')         \u002F\u002F copy with index 0 replaced\n```\n\nThey make immutable updates concise — especially `with`, which replaces the\nold `[...a.slice(0,i), val, ...a.slice(i+1)]` dance.\n",{"id":611,"difficulty":88,"q":612,"a":613},"search-performance","When should you use a Set or Map instead of array searching?","Repeated `includes`\u002F`indexOf` lookups are **O(n)** each — O(n·m) overall.\nA **`Set`** gives O(1) membership tests.\n\n```js\nconst seen = new Set(bigArray)\nqueries.filter(q => seen.has(q))   \u002F\u002F O(1) per lookup\n```\n\nRule of thumb: if you search the same collection more than a handful of\ntimes, build a `Set`\u002F`Map` index once and query that instead.\n",{"id":615,"difficulty":88,"q":616,"a":617},"dedupe-sorted","How do you remove duplicates, optionally keeping order?","A **`Set`** dedupes and preserves first-seen insertion order in one line.\n\n```js\nconst unique = [...new Set(arr)]   \u002F\u002F order preserved\n```\n\nFor objects (reference equality won't help), dedupe by a key with a `Map`:\n\n```js\nconst byId = [...new Map(users.map(u => [u.id, u])).values()]\n```\n",{"id":619,"difficulty":161,"q":620,"a":621},"sort-comparator-cost","Why can repeated work inside a comparator be a performance problem?","The comparator runs **O(n log n)** times, so any expensive computation\ninside it is repeated constantly. Precompute keys once with a\n**Schwartzian transform**.\n\n```js\nconst sorted = items\n  .map(x => ({ x, key: expensiveKey(x) }))  \u002F\u002F compute once\n  .sort((a, b) => a.key - b.key)\n  .map(o => o.x)                              \u002F\u002F unwrap\n```\n\nThis trades a little memory for far fewer key computations than calling\n`expensiveKey` inside `sort`.\n",{"id":623,"difficulty":96,"q":624,"a":625},"find-default","What does find return when nothing matches, and why be careful?","It returns **`undefined`**. Destructuring or accessing properties on the\nresult without a guard then throws.\n\n```js\nconst u = users.find(u => u.id === 99)\nu.name              \u002F\u002F TypeError if not found\nu?.name             \u002F\u002F optional chaining\nconst { name } = u ?? {}  \u002F\u002F safe default\n```\n\nAlways treat `find`'s result as possibly `undefined`.\n",{"id":627,"difficulty":96,"q":628,"a":629},"indexof-vs-search-string","Does array indexOf relate to string indexOf?","They share a name and a `-1`-on-miss convention, but operate on different\nthings. **Array** `indexOf` matches an element by `===`; **string**\n`indexOf` finds a **substring**.\n\n```js\n['ab', 'cd'].indexOf('b')   \u002F\u002F -1  (no element equals 'b')\n'abcd'.indexOf('b')         \u002F\u002F 1   (substring position)\n```\n\nDon't expect array `indexOf` to do partial\u002Fsubstring matching — use\n`some(s => s.includes('b'))` for that.\n",{"id":631,"difficulty":161,"q":632,"a":633},"sort-locale-numeric","How do you sort strings that contain numbers \"naturally\" (file2 \u003C file10)?","Default and `localeCompare` without options give `file10 \u003C file2`\n(lexicographic). Pass `{ numeric: true }` for **natural sort**.\n\n```js\n['file10','file2'].sort()  \u002F\u002F ['file10','file2']\n['file10','file2'].sort((a,b)=>\n  a.localeCompare(b, undefined, { numeric: true }))\n\u002F\u002F ['file2','file10']\n```\n\nCombine with `sensitivity: 'base'` for case\u002Faccent-insensitive natural\nordering of filenames and version strings.\n",{"id":635,"difficulty":96,"q":636,"a":637},"empty-array-search","What do searching methods return on an empty array?","Consistent, safe defaults: `indexOf`\u002F`findIndex` return `-1`,\n`find` returns `undefined`, `includes`\u002F`some` return `false`, and\n`every` returns `true`.\n\n```js\n[].indexOf('x')   \u002F\u002F -1\n[].find(Boolean)  \u002F\u002F undefined\n[].some(Boolean)  \u002F\u002F false\n[].every(Boolean) \u002F\u002F true   vacuously\n```\n\nThe `every === true` on empty is the one that surprises people in\nvalidation logic — guard for emptiness if \"all valid\" shouldn't pass on no\ndata.\n",{"description":86},"JavaScript array searching and sorting interview questions — indexOf, includes, find, the sort() coercion gotcha, numeric comparators, stable sort, toSorted and sorting objects.","javascript\u002Farrays\u002Fsearching-sorting","Searching & Sorting","rwKZ3UXQprDpLSR117P9VFRLTkhBfPapY8I3dIMex0Q",{"id":644,"title":645,"body":646,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":650,"navigation":91,"order":29,"path":651,"questions":652,"related":224,"seo":785,"seoDescription":786,"stem":787,"subtopic":788,"topic":37,"topicSlug":39,"updated":789,"__hash__":790},"qa\u002Fjavascript\u002Fasync\u002Fevent-loop.md","Event Loop",{"type":83,"value":647,"toc":648},[],{"title":86,"searchDepth":29,"depth":29,"links":649},[],{},"\u002Fjavascript\u002Fasync\u002Fevent-loop",[653,657,661,665,669,673,677,681,685,689,693,697,701,705,709,713,717,721,725,729,733,737,741,745,749,753,757,761,765,769,773,777,781],{"id":654,"difficulty":88,"q":655,"a":656},"what-is-event-loop","What is the event loop?","JavaScript runs on a **single thread** — one call stack, one thing at a time.\nThe event loop is the coordinator that lets that single thread *appear*\nconcurrent: it repeatedly checks \"is the call stack empty?\" and, when it is,\npulls the next queued callback and pushes it onto the stack to run.\n\nThe pieces involved:\n\n- **Call stack** — the function currently executing.\n- **Web\u002FNode APIs** — timers, network, I\u002FO that run *outside* the engine and\n  hand a callback back when done.\n- **Task & microtask queues** — where those finished callbacks wait.\n\n```js\nwhile (true) {\n  runUntilStackEmpty()   \u002F\u002F execute current synchronous work\n  drainMicrotasks()      \u002F\u002F then ALL queued microtasks\n  if (oneMacrotask) run(oneMacrotask) \u002F\u002F then exactly one macrotask, repeat\n}\n```\n\nSo async code never \"interrupts\" running code — it waits until the stack is\nclear, which is why the event loop is the heart of every \"what's the output\norder?\" interview question.\n",{"id":658,"difficulty":96,"q":659,"a":660},"call-stack","What is the call stack?","The call stack is a **LIFO (last-in, first-out)** structure that tracks where\nthe program is in its execution. Calling a function **pushes** a frame (its\nlocal variables and return address); returning **pops** it. JavaScript has\nexactly one call stack, so it executes one frame at a time.\n\n```js\nfunction a() { b() }\nfunction b() { c() }\nfunction c() { throw new Error('boom') }\na()\n\u002F\u002F Stack at the throw (top first): c -> b -> a -> (global)\n\u002F\u002F That ordering is literally what a stack trace prints.\n```\n\nTwo consequences worth naming in an interview: deep\u002Finfinite recursion\noverflows the stack (`Maximum call stack size exceeded`), and because there's\nonly one stack, any long synchronous function **blocks** everything else until\nit returns.\n",{"id":662,"difficulty":161,"q":663,"a":664},"macro-micro","What is the difference between the macrotask and microtask queues?","There are two priority levels of queued work, and the event loop treats them\nvery differently:\n\n- **Macrotasks** (a.k.a. \"tasks\"): `setTimeout`, `setInterval`,\n  `setImmediate`, I\u002FO callbacks, UI events. The loop runs **one** per\n  iteration.\n- **Microtasks**: promise `.then`\u002F`catch`\u002F`finally` callbacks,\n  `queueMicrotask`, `await` continuations, `MutationObserver`.\n\nThe critical rule: after each macrotask (and after the initial synchronous\nscript), the engine **drains the entire microtask queue** — including any\nmicrotasks those microtasks schedule — *before* picking up the next macrotask\nor rendering.\n\n```js\nsetTimeout(() => console.log('macro'), 0)\nPromise.resolve()\n  .then(() => console.log('micro 1'))\n  .then(() => console.log('micro 2'))\n\u002F\u002F micro 1, micro 2, macro\n\u002F\u002F Both microtasks finish before the timer, even with a 0ms delay.\n```\n\nThat \"microtasks always win\" behavior is why a resolved promise consistently\nbeats a `setTimeout(0)`.\n",{"id":666,"difficulty":161,"q":667,"a":668},"ordering","What is the output order of this snippet?","```js\nconsole.log('A')\nsetTimeout(() => console.log('B'))\nPromise.resolve().then(() => console.log('C'))\nconsole.log('D')\n```\n\n**Output: `A D C B`.** Walk it through the way you would on a whiteboard:\n\n1. `console.log('A')` — synchronous, runs now -> **A**.\n2. `setTimeout(...)` — hands the callback to the timer API; it'll be queued as\n   a **macrotask**. Nothing prints yet.\n3. `Promise.resolve().then(...)` — schedules its callback as a **microtask**.\n   Nothing prints yet.\n4. `console.log('D')` — synchronous -> **D**.\n5. Script finishes, stack is empty -> drain **microtasks** -> **C**.\n6. Next macrotask runs -> **B**.\n\nThe takeaway: all synchronous code first, then every microtask, then the next\nmacrotask.\n",{"id":670,"difficulty":88,"q":671,"a":672},"blocking","What happens if you run a long synchronous loop?","It **blocks the single thread**. While the loop runs the call stack never\nempties, so the event loop can't pull anything from the queues: timers don't\nfire on time, promise callbacks wait, clicks\u002Fscroll feel frozen, and the page\ncan't repaint (the dreaded \"page unresponsive\").\n\n```js\nconst end = Date.now() + 3000\nwhile (Date.now() \u003C end) {} \u002F\u002F freezes the tab for 3 full seconds\nconsole.log('finally free')\n```\n\nFixes: break the work into chunks that yield to the loop (`setTimeout`,\n`requestIdleCallback`), or move CPU-heavy work off the main thread into a **Web\nWorker** (browser) \u002F **Worker thread** (Node) so the UI stays responsive.\n",{"id":674,"difficulty":161,"q":675,"a":676},"starvation","Can microtasks starve the event loop?","Yes. Because the engine drains the **whole** microtask queue before moving on,\na microtask that keeps scheduling more microtasks creates a queue that never\nempties — so macrotasks (timers, I\u002FO) and rendering are postponed\nindefinitely. The tab effectively hangs even though \"async\" code is running.\n\n```js\nfunction loop() {\n  queueMicrotask(loop) \u002F\u002F re-queues itself forever -> macrotasks never run\n}\nloop()\nsetTimeout(() => console.log('I will never print'), 0)\n```\n\nTo avoid starvation, yield to the macrotask queue for repeated\u002Flong work\n(`setTimeout`, `MessageChannel`, or `await` a real async boundary) so the loop\ngets a chance to run timers and paint frames between chunks.\n",{"id":678,"difficulty":88,"q":679,"a":680},"queuemicrotask","What is queueMicrotask?","`queueMicrotask(fn)` schedules a callback to run as a **microtask** — after the\ncurrent synchronous code finishes but before the next macrotask. It's the direct\nway to queue a microtask without abusing `Promise.resolve().then()`.\n\n```js\nconsole.log('sync')\nqueueMicrotask(() => console.log('microtask'))\nconsole.log('sync 2')\n\u002F\u002F sync, sync 2, microtask\n```\n\nUse it to defer work to \"just after this task\" while still beating timers — e.g.\nbatching DOM reads or ensuring a callback runs after the current call stack\nunwinds but ASAP.\n",{"id":682,"difficulty":161,"q":683,"a":684},"raf","How does requestAnimationFrame fit into the event loop?","`requestAnimationFrame(cb)` schedules `cb` to run **right before the next\nrepaint**, typically ~60 times per second. It's neither a macrotask nor a\nmicrotask — the browser runs rAF callbacks in a dedicated step of the rendering\npipeline, just before layout\u002Fpaint.\n\n```js\nrequestAnimationFrame(() => {\n  el.style.transform = `translateX(${x}px)` \u002F\u002F applied in sync with the frame\n})\n```\n\nUse it for animations and visual updates so they're synced to the display\nrefresh (no tearing, no wasted frames). Unlike `setTimeout`, it pauses in\nbackground tabs.\n",{"id":686,"difficulty":88,"q":687,"a":688},"settimeout-clamp","Is setTimeout(fn, 0) really zero milliseconds?","No. `setTimeout(fn, 0)` means \"run as soon as possible **as a macrotask**,\" not\ninstantly. The HTML spec also **clamps** nested timeouts to a minimum (~4ms after\n5 levels of nesting), and the callback still waits for the stack to clear and all\nmicrotasks to drain.\n\n```js\nsetTimeout(() => console.log('timer'), 0)\nPromise.resolve().then(() => console.log('microtask'))\n\u002F\u002F microtask runs first — the \"0ms\" timer is still a macrotask\n```\n\nSo `setTimeout(0)` is \"defer to the next task,\" useful for yielding, but never a\nprecise or immediate timer.\n",{"id":690,"difficulty":161,"q":691,"a":692},"node-vs-browser","How does the event loop differ between Node.js and the browser?","The core idea (stack + queues + microtask draining) is the same, but the\nimplementations differ:\n\n- The **browser** loop is defined by the HTML spec and integrates with\n  **rendering** (rAF, paint, layout).\n- **Node** uses **libuv** with distinct **phases** (timers, pending callbacks,\n  poll, check, close) and adds `process.nextTick` and `setImmediate`, with no\n  rendering step.\n\n```js\n\u002F\u002F Node-only ordering nuance:\nsetImmediate(() => console.log('immediate'))\nsetTimeout(() => console.log('timeout'), 0)\nprocess.nextTick(() => console.log('nextTick'))\n\u002F\u002F nextTick runs before both; immediate vs timeout order can vary\n```\n\nMicrotasks (promises) drain between phases\u002Ftasks in both environments.\n",{"id":694,"difficulty":161,"q":695,"a":696},"nexttick","What is process.nextTick in Node and how does it differ from microtasks?","`process.nextTick(fn)` queues `fn` to run **after the current operation\ncompletes**, before the event loop continues — and crucially **before** the\nPromise microtask queue. So Node effectively has two micro-queues, with\n`nextTick` having higher priority.\n\n```js\nPromise.resolve().then(() => console.log('promise'))\nprocess.nextTick(() => console.log('nextTick'))\n\u002F\u002F nextTick, promise\n```\n\nBecause it preempts everything, recursively scheduling `nextTick` can **starve**\nthe loop entirely. Prefer `queueMicrotask`\u002Fpromises unless you specifically need\nits priority.\n",{"id":698,"difficulty":161,"q":699,"a":700},"await-puzzle","What is the output order of this async\u002Fawait snippet?","```js\nconsole.log('1')\nasync function f() {\n  console.log('2')\n  await null\n  console.log('3')\n}\nf()\nconsole.log('4')\n\u002F\u002F Output: 1, 2, 4, 3\n```\n\n`f()` runs synchronously up to the `await` (logs **2**). `await` suspends the\nfunction and schedules the rest (`console.log('3')`) as a **microtask**, so\ncontrol returns to the caller and **4** logs. After the synchronous code, the\nmicrotask runs -> **3**. The body before the first `await` is synchronous; only\nwhat follows is deferred.\n",{"id":702,"difficulty":161,"q":703,"a":704},"rendering-tasks","When does the browser render relative to tasks and microtasks?","The browser tries to render at most **once per frame** (~16.7ms at 60fps), and it\ndoes so **after** the current macrotask **and** its full microtask queue have\ncompleted — never in the middle of a task.\n\n```\nmacrotask -> drain microtasks -> (rAF callbacks) -> style\u002Flayout\u002Fpaint -> next macrotask\n```\n\nConsequence: synchronous DOM changes within one task aren't painted individually\n— only the final state shows. And a long task blocks rendering entirely, which is\nwhy long synchronous work freezes the page.\n",{"id":706,"difficulty":161,"q":707,"a":708},"await-scheduling","How does await schedule the rest of an async function?","`await x` pauses the function and registers the **remaining code as a\ncontinuation** (a `.then` callback on `x`), which runs as a **microtask** once\n`x` settles. The async function is essentially rewritten into promise\ncontinuations by the engine.\n\n```js\nasync function g() {\n  const a = await fetchA() \u002F\u002F everything below becomes a microtask continuation\n  const b = await fetchB() \u002F\u002F ...and so does this, after a resolves\n  return a + b\n}\n```\n\nSo each `await` introduces a microtask boundary. This is why code after `await`\nalways runs after the current synchronous task, never inline.\n",{"id":710,"difficulty":88,"q":711,"a":712},"settimeout-recursion","What is the difference between setInterval and recursive setTimeout?","`setInterval` queues the callback every N ms **regardless of how long it takes**\n— if the callback is slow, executions can pile up or overlap conceptually.\n**Recursive `setTimeout`** schedules the next run only **after** the current one\nfinishes, guaranteeing a gap.\n\n```js\n\u002F\u002F guarantees ≥1s between completions\nfunction poll() {\n  doWork()\n  setTimeout(poll, 1000)\n}\nsetTimeout(poll, 1000)\n```\n\nRecursive `setTimeout` is preferred for variable-duration work and for adapting\nthe delay dynamically; `setInterval` is fine for short, fixed-cadence ticks.\n",{"id":714,"difficulty":161,"q":715,"a":716},"promise-chain-order","How are chained .then callbacks ordered against each other?","Each `.then` schedules its callback as a **separate microtask**, queued only when\nthe previous link resolves. So two independent chains **interleave** one\nmicrotask at a time.\n\n```js\nPromise.resolve().then(() => console.log('A1')).then(() => console.log('A2'))\nPromise.resolve().then(() => console.log('B1')).then(() => console.log('B2'))\n\u002F\u002F A1, B1, A2, B2\n```\n\n`A1` and `B1` are queued first; running `A1` queues `A2`, running `B1` queues\n`B2`. The engine drains the queue in FIFO order, producing the interleaving.\n",{"id":718,"difficulty":88,"q":719,"a":720},"yield-main-thread","How do you yield to the event loop to keep the UI responsive?","Break long synchronous work into chunks and **schedule the next chunk as a\nmacrotask** so the loop can run timers, handle input, and paint in between.\n\n```js\nfunction processChunk(i) {\n  const end = Math.min(i + 1000, data.length)\n  for (; i \u003C end; i++) handle(data[i])\n  if (i \u003C data.length) setTimeout(() => processChunk(i), 0) \u002F\u002F yield\n}\nprocessChunk(0)\n```\n\nModern options include `scheduler.yield()`, `MessageChannel`, or\n`requestIdleCallback`. For pure CPU work, a **Web Worker** keeps the main thread\nfree entirely.\n",{"id":722,"difficulty":161,"q":723,"a":724},"node-phases","What are the phases of the Node.js event loop?","libuv runs the loop through ordered phases, each with its own callback queue:\n\n1. **timers** — `setTimeout`\u002F`setInterval` callbacks.\n2. **pending callbacks** — deferred I\u002FO callbacks.\n3. **poll** — retrieve new I\u002FO events; execute I\u002FO callbacks.\n4. **check** — `setImmediate` callbacks.\n5. **close** — `close` event callbacks.\n\nBetween **every** phase, Node drains `process.nextTick` and the microtask\n(promise) queues. This phased structure is why `setImmediate` (check) and\n`setTimeout(0)` (timers) can fire in different orders depending on context.\n",{"id":726,"difficulty":161,"q":727,"a":728},"setimmediate","What is the difference between setImmediate and setTimeout(0) in Node?","`setImmediate` runs in the **check** phase, after the **poll** phase, while\n`setTimeout(0)` runs in the **timers** phase at the start of the next loop. Inside\nan **I\u002FO callback**, `setImmediate` is deterministically first; at the top level\ntheir order is non-deterministic.\n\n```js\nconst fs = require('fs')\nfs.readFile(__filename, () => {\n  setTimeout(() => console.log('timeout'), 0)\n  setImmediate(() => console.log('immediate'))\n  \u002F\u002F inside I\u002FO: \"immediate\" always logs first\n})\n```\n\nRule: to run \"after the current I\u002FO, ASAP,\" use `setImmediate`.\n",{"id":730,"difficulty":88,"q":731,"a":732},"promise-executor-sync","Does the Promise executor function run synchronously?","Yes. The function you pass to `new Promise((resolve, reject) => {...})` runs\n**synchronously, immediately**, as part of constructing the promise. Only the\n`.then`\u002F`.catch` **callbacks** are asynchronous (microtasks).\n\n```js\nconsole.log('start')\nnew Promise(resolve => {\n  console.log('executor')   \u002F\u002F runs now, synchronously\n  resolve()\n}).then(() => console.log('then'))\nconsole.log('end')\n\u002F\u002F start, executor, end, then\n```\n\nA common misconception is that everything about a promise is async — the executor\nbody is not.\n",{"id":734,"difficulty":88,"q":735,"a":736},"await-nonpromise","What happens when you await a non-promise value?","`await` wraps any non-promise in `Promise.resolve(value)`, so the value comes back\nas-is — but the function **still suspends for one microtask tick**. So even\n`await 5` defers the rest of the function.\n\n```js\nasync function f() {\n  console.log('before')\n  await 5            \u002F\u002F not a promise, but still yields a microtask\n  console.log('after')\n}\nf()\nconsole.log('sync')\n\u002F\u002F before, sync, after\n```\n\nSo `await` always introduces an async boundary, even for plain values — handy to\nknow for ordering puzzles.\n",{"id":738,"difficulty":88,"q":739,"a":740},"async-not-multithread","Does asynchronous code mean JavaScript is multithreaded?","No. JavaScript runs on a **single thread**; async just means work is **scheduled**\nto run later rather than blocking. The *waiting* (timers, network, file I\u002FO)\nhappens outside the JS engine (in the browser\u002FOS\u002Flibuv), but your callbacks all\nrun one-at-a-time on the same thread.\n\n```js\nsetTimeout(() => console.log('later'), 1000) \u002F\u002F the timer is handled elsewhere;\n\u002F\u002F the callback still runs on the single JS thread when the stack is free\n```\n\nTrue parallelism in JS requires **Web Workers** \u002F **worker threads**, which run\nseparate threads communicating via messages.\n",{"id":742,"difficulty":96,"q":743,"a":744},"why-single-thread","Why is JavaScript single-threaded?","JavaScript was designed single-threaded to keep the **DOM model simple** — if\nmultiple threads could mutate the DOM concurrently, you'd need locks everywhere\nand face race conditions on every UI update. A single thread plus the event loop\ngives concurrency (handling many things) without the complexity of parallelism.\n\n```js\n\u002F\u002F no data races: only one piece of JS touches `count` at a time\nlet count = 0\nbutton.onclick = () => count++\n```\n\nThe trade-off is that CPU-heavy work blocks everything — solved by offloading to\nWeb Workers when needed.\n",{"id":746,"difficulty":96,"q":747,"a":748},"callback-queue","What is the callback (task) queue?","The callback queue (a.k.a. task\u002Fmacrotask queue) holds callbacks that are\n**ready to run** but waiting for the call stack to clear — completed timers,\nresolved I\u002FO, dispatched events. The event loop moves one of them onto the stack\neach iteration.\n\n```js\nbutton.addEventListener('click', handler) \u002F\u002F handler is queued when clicked\nsetTimeout(cb, 100)                        \u002F\u002F cb is queued ~100ms later\n```\n\nIt's strictly FIFO per task source, and the loop only pulls from it when the\nstack is empty and microtasks are drained.\n",{"id":750,"difficulty":161,"q":751,"a":752},"nested-timeout-order","What is the order of nested setTimeout and promise callbacks?","```js\nsetTimeout(() => {\n  console.log('timeout 1')\n  Promise.resolve().then(() => console.log('promise in timeout'))\n}, 0)\nsetTimeout(() => console.log('timeout 2'), 0)\n\u002F\u002F timeout 1, promise in timeout, timeout 2\n```\n\nEach macrotask is followed by a **full microtask drain** before the next\nmacrotask. So after \"timeout 1\" runs, its queued promise microtask executes\n**before** \"timeout 2\". This \"microtasks between every macrotask\" rule is the key\nto these puzzles.\n",{"id":754,"difficulty":161,"q":755,"a":756},"microtask-checkpoint","What is a microtask checkpoint?","A microtask checkpoint is the point where the engine **drains the entire\nmicrotask queue**. It happens after the current macrotask completes (the stack\nempties) and also after certain operations like a callback returning. All pending\nmicrotasks — and any they schedule — run to completion before the next macrotask\nor render.\n\n```js\n\u002F\u002F everything queued via .then\u002FqueueMicrotask runs at the next checkpoint,\n\u002F\u002F before any setTimeout callback\n```\n\nUnderstanding checkpoints explains why microtasks always \"win\" and why they can\nstarve the loop if they keep scheduling more.\n",{"id":758,"difficulty":161,"q":759,"a":760},"ordering-puzzle2","Trace the output of mixed sync, await, promise and setTimeout.","```js\nconsole.log('A')\nsetTimeout(() => console.log('B'), 0)\nPromise.resolve().then(() => console.log('C'))\n;(async () => {\n  console.log('D')\n  await null\n  console.log('E')\n})()\nconsole.log('F')\n\u002F\u002F A, D, F, C, E, B\n```\n\nSync first: **A**, then the async IIFE runs to its `await` -> **D**, then **F**.\nMicrotasks drain next: **C** (queued before the await continuation), then **E**.\nFinally the macrotask: **B**. Order of microtasks follows the order they were\nqueued.\n",{"id":762,"difficulty":88,"q":763,"a":764},"input-responsiveness","How do long tasks hurt responsiveness (INP)?","A \"long task\" (>50ms of synchronous work) monopolizes the single thread, so the\nevent loop can't process the click\u002Fkeypress callback or repaint — the user\nperceives lag. This directly worsens the **INP (Interaction to Next Paint)**\nmetric.\n\n```js\nbutton.onclick = () => {\n  heavyCompute() \u002F\u002F blocks -> the visual response is delayed\n}\n```\n\nFixes: break work into chunks that yield, defer non-urgent work\n(`requestIdleCallback`), debounce, or move computation to a Web Worker so input\nhandling and painting stay snappy.\n",{"id":766,"difficulty":88,"q":767,"a":768},"raf-vs-timeout-animation","Why use requestAnimationFrame instead of setTimeout for animation?","`requestAnimationFrame` runs **in sync with the display refresh** (right before\npaint) and **pauses in background tabs**, so animations are smooth and don't waste\nCPU\u002Fbattery. `setTimeout` fires on an arbitrary schedule unrelated to the frame,\ncausing dropped or doubled frames and jank.\n\n```js\nfunction animate() {\n  move()\n  requestAnimationFrame(animate) \u002F\u002F one update per frame, perfectly timed\n}\nrequestAnimationFrame(animate)\n```\n\nrAF also self-throttles to the screen's refresh rate, whereas a fixed\n`setTimeout(16)` drifts and can't adapt to 120Hz displays.\n",{"id":770,"difficulty":88,"q":771,"a":772},"one-macrotask-per-tick","Why does the loop process only one macrotask per iteration?","Running one macrotask then draining microtasks (and giving rendering a chance)\nkeeps the system **responsive and fair**: it prevents a flood of queued tasks\nfrom blocking input handling and painting, and ensures microtask-based work\n(promises) completes promptly between tasks.\n\n```\n[1 macrotask] -> [all microtasks] -> [maybe render] -> [1 macrotask] -> ...\n```\n\nIf the loop drained the whole macrotask queue at once, a burst of timers\u002Fevents\ncould lock out rendering and user input until they all finished.\n",{"id":774,"difficulty":96,"q":775,"a":776},"sync-vs-async-diff","What is the difference between synchronous and asynchronous code?","**Synchronous** code runs top-to-bottom, each statement **blocking** until it\nfinishes. **Asynchronous** code starts an operation and **continues without\nwaiting**, handling the result later via a callback\u002Fpromise — so the thread isn't\nblocked.\n\n```js\nconst data = readFileSync('f.txt') \u002F\u002F sync: blocks here until done\nreadFile('f.txt', (e, data) => {}) \u002F\u002F async: returns immediately, callback later\n```\n\nAsync is essential in single-threaded JS so that slow I\u002FO (network, disk) doesn't\nfreeze the UI — the event loop schedules the continuation when the result is\nready.\n",{"id":778,"difficulty":161,"q":779,"a":780},"workers-offload","How do Web Workers relate to the event loop?","A Web Worker runs JavaScript on a **separate thread with its own event loop**, so\nCPU-heavy work there doesn't block the main thread's loop (and thus the UI). They\ncommunicate via `postMessage`, which queues a **message-event** (macrotask) on\nthe receiving side.\n\n```js\nconst worker = new Worker('heavy.js')\nworker.postMessage(bigData)\nworker.onmessage = e => render(e.data) \u002F\u002F runs on main thread when free\n```\n\nWorkers don't share memory by default (except `SharedArrayBuffer`), avoiding data\nraces. Use them to keep the main loop free for input and rendering.\n",{"id":782,"difficulty":88,"q":783,"a":784},"defer-with-tasks","How can you defer work to the next tick using the event loop?","To run something **after** the current synchronous code without blocking, schedule\nit on a queue. The choice of queue controls priority:\n\n```js\nqueueMicrotask(fn)        \u002F\u002F ASAP: before the next render\u002Fmacrotask\nPromise.resolve().then(fn) \u002F\u002F also a microtask\nsetTimeout(fn, 0)          \u002F\u002F next macrotask (after microtasks + maybe a paint)\nrequestAnimationFrame(fn)  \u002F\u002F before the next paint\n```\n\nPick a **microtask** when the deferral must beat rendering\u002Ftimers, and a\n**macrotask** when you want to yield the thread (let input\u002Fpaint happen) before\ncontinuing.\n",{"description":86},"JavaScript event loop interview questions — the call stack, task and microtask queues, and how asynchronous code is scheduled.","javascript\u002Fasync\u002Fevent-loop","The Event Loop","2026-06-17","v5VF_8JManXxxPa5kLV8PcWEglG8nn9bwl29BN9yPxg",{"id":792,"title":793,"body":794,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":798,"navigation":91,"order":11,"path":799,"questions":800,"related":224,"seo":936,"seoDescription":937,"stem":938,"subtopic":939,"topic":37,"topicSlug":39,"updated":789,"__hash__":940},"qa\u002Fjavascript\u002Fasync\u002Fpromises.md","Promises",{"type":83,"value":795,"toc":796},[],{"title":86,"searchDepth":29,"depth":29,"links":797},[],{},"\u002Fjavascript\u002Fasync\u002Fpromises",[801,805,809,813,817,821,825,829,833,836,840,844,848,852,856,860,864,868,872,876,880,884,888,892,896,900,904,908,912,916,920,924,928,932],{"id":802,"difficulty":96,"q":803,"a":804},"what-is-promise","What is a Promise?","A Promise is an object representing the **eventual** result of an asynchronous\noperation — a placeholder for a value you don't have yet. It lives in one of\nthree states:\n\n- `pending` — the starting state, not yet settled.\n- `fulfilled` — completed successfully, carries a value.\n- `rejected` — failed, carries a reason (usually an `Error`).\n\n```js\nconst p = new Promise((resolve, reject) => {\n  setTimeout(() => resolve('done'), 100) \u002F\u002F settles after 100ms\n})\np.then(value => console.log(value)) \u002F\u002F 'done'\n```\n\nTwo properties make promises predictable: they're **settled once** (a\npending promise transitions to fulfilled *or* rejected exactly one time and\nthen its state\u002Fvalue are **immutable**), and `.then`\u002F`.catch` always run\n**asynchronously** as microtasks — never synchronously, even for an\nalready-resolved promise.\n",{"id":806,"difficulty":88,"q":807,"a":808},"async-await","What is async\u002Fawait and how does it relate to promises?","`async`\u002F`await` is **syntactic sugar over promises** — it doesn't add new\ncapabilities, it makes promise code read like ordinary sequential code. Two\nrules: an `async` function **always returns a promise** (any value you return\nis wrapped in a resolved promise; any throw becomes a rejected one), and\n`await` **pauses** the function until the awaited promise settles, then\nresumes with its value.\n\n```js\nasync function load() {\n  const res = await fetch('\u002Fapi')   \u002F\u002F pause until the request resolves\n  return res.json()                 \u002F\u002F also awaited by the caller\n}\nload().then(data => console.log(data)) \u002F\u002F still a promise underneath\n```\n\nCrucially, `await` only suspends the *current async function* — the rest of\nthe program keeps running. Under the hood the code after an `await` becomes a\n`.then` continuation scheduled as a microtask.\n",{"id":810,"difficulty":88,"q":811,"a":812},"error-handling","How do you handle errors with promises and async\u002Fawait?","With raw promises, attach `.catch()` to handle a rejection anywhere up the\nchain. With `async`\u002F`await`, an awaited rejected promise **throws**, so you use\na normal `try\u002Fcatch`.\n\n```js\n\u002F\u002F promise style\nload().then(use).catch(err => console.error(err))\n\n\u002F\u002F async\u002Fawait style — reads like synchronous try\u002Fcatch\ntry {\n  const data = await load()\n  use(data)\n} catch (err) {\n  console.error(err)\n} finally {\n  hideSpinner() \u002F\u002F runs whether it succeeded or failed\n}\n```\n\nGotchas interviewers probe: a single `.catch()` at the end catches errors from\n*every* prior step in the chain; an **unhandled** rejection triggers an\n`unhandledrejection` event\u002Fwarning; and forgetting to `await` (or `return`) a\npromise inside a `try` means its rejection escapes the `catch` entirely.\n",{"id":814,"difficulty":88,"q":815,"a":816},"promise-all","What is the difference between Promise.all and Promise.allSettled?","Both take an iterable of promises and run them concurrently, but they differ in\nhow they handle failure:\n\n- `Promise.all` **short-circuits**: it fulfills with an array of all values\n  once **every** promise fulfills, but rejects **immediately** the moment\n  **any one** rejects — you lose the results of the others.\n- `Promise.allSettled` **never rejects**: it waits for **every** promise to\n  settle and resolves with an array of `{ status, value }` or\n  `{ status, reason }` objects, so you can inspect each outcome.\n\n```js\nconst results = await Promise.allSettled([fetchA(), fetchB(), fetchC()])\nresults.forEach(r => {\n  if (r.status === 'fulfilled') console.log('ok', r.value)\n  else console.log('failed', r.reason)\n})\n```\n\nReach for `all` when you need *all-or-nothing* (one failure should abort);\nreach for `allSettled` when you want every result regardless of partial\nfailures (e.g. a dashboard of independent widgets).\n",{"id":818,"difficulty":88,"q":819,"a":820},"promise-race","What do Promise.race and Promise.any do?","Both settle based on the **first** promise to finish, but they disagree on what\ncounts:\n\n- `Promise.race` settles as soon as the first promise **settles** — whether it\n  fulfills *or* rejects. The first one to cross the line wins, error or not.\n- `Promise.any` resolves with the first promise to **fulfill**, ignoring\n  rejections. It only rejects if **all** of them reject, with an\n  `AggregateError` bundling every reason.\n\n```js\n\u002F\u002F timeout pattern — race the work against a timer\nconst data = await Promise.race([\n  fetch('\u002Fapi'),\n  new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), 5000)),\n])\n\n\u002F\u002F first successful mirror wins; only fails if every mirror is down\nconst fastest = await Promise.any([fetch(mirror1), fetch(mirror2)])\n```\n\nMnemonic: **race** cares about *first to finish*, **any** cares about *first to\nsucceed*.\n",{"id":822,"difficulty":161,"q":823,"a":824},"sequential-parallel","How do you run async tasks in parallel vs sequentially?","The difference is **when you start** each task. `await` inside a loop starts\nthe next task only after the previous one resolves — that's **sequential** and\noften an accidental performance bug. To go **parallel**, kick them all off\nfirst (so they run concurrently), then `await` them together.\n\n```js\n\u002F\u002F sequential: ~A + B + C total time\nfor (const url of urls) {\n  results.push(await fetch(url))\n}\n\n\u002F\u002F parallel: ~max(A, B, C) total time\nconst results = await Promise.all(urls.map(url => fetch(url)))\n```\n\nUse sequential intentionally when each step **depends on the previous one's\nresult** or you must avoid hammering a rate-limited API. Use parallel when the\ntasks are independent — it can be dramatically faster.\n",{"id":826,"difficulty":161,"q":827,"a":828},"microtask","Why does an awaited promise callback run before a setTimeout?","Because promise continuations are scheduled as **microtasks**, while\n`setTimeout` callbacks are **macrotasks** — and the event loop drains the\n*entire* microtask queue after the current synchronous code, *before* it ever\nreaches the next macrotask.\n\n```js\nconsole.log(1)\nsetTimeout(() => console.log(2), 0)        \u002F\u002F macrotask\nPromise.resolve().then(() => console.log(3)) \u002F\u002F microtask\nconsole.log(4)\n\u002F\u002F Output: 1, 4, 3, 2 — the promise (3) beats the timer (2)\n```\n\nSo even `setTimeout(fn, 0)` is effectively \"run after all pending microtasks,\"\nwhich is why a resolved promise's `.then` always fires first.\n",{"id":830,"difficulty":88,"q":831,"a":832},"promisify","How do you convert a callback-based API to a promise?","Wrap the callback API in `new Promise(...)` and translate the callback's\noutcome into `resolve`\u002F`reject`. For Node-style `(err, value)` callbacks, the\nconvention is \"error first\": reject on `err`, otherwise resolve with the value.\n\n```js\n\u002F\u002F simple timer\nconst wait = ms => new Promise(resolve => setTimeout(resolve, ms))\n\n\u002F\u002F wrapping a Node-style error-first callback\nconst readFileAsync = path =>\n  new Promise((resolve, reject) => {\n    fs.readFile(path, 'utf8', (err, data) => {\n      if (err) reject(err)\n      else resolve(data)\n    })\n  })\n```\n\nIn Node you'd usually reach for the built-in `util.promisify` instead of\nhand-rolling this, but interviewers like to see you can build it from scratch.\n",{"id":156,"difficulty":88,"q":834,"a":835},"How does promise chaining work?","Each `.then` returns a **new promise** that resolves with whatever its callback\nreturns, so you can chain steps where each receives the previous result. This\nflattens nested callbacks into a linear sequence.\n\n```js\nfetch('\u002Fapi\u002Fuser')\n  .then(res => res.json())     \u002F\u002F returns parsed body\n  .then(user => fetch(`\u002Fapi\u002Fposts\u002F${user.id}`))\n  .then(res => res.json())\n  .then(posts => console.log(posts))\n  .catch(err => console.error(err))\n```\n\nThe chain runs step by step; returning a value passes it down, returning a\npromise waits for it. A single trailing `.catch` handles errors from any step.\n",{"id":837,"difficulty":88,"q":838,"a":839},"then-return-value","What does .then return and why does it matter?","`.then` always returns a **new promise**. What that promise resolves to depends on\nthe callback: a plain value -> resolves with it; a promise -> **adopts** that\npromise's eventual value (flattening); a `throw` -> rejects.\n\n```js\nPromise.resolve(1)\n  .then(x => x + 1)               \u002F\u002F resolves 2\n  .then(x => Promise.resolve(x*10)) \u002F\u002F resolves 20 (adopted)\n  .then(x => { throw new Error() }) \u002F\u002F rejects\n  .then(x => console.log('skipped'))\n  .catch(() => console.log('caught'))\n```\n\nBecause each `.then` is a fresh promise, chaining and error propagation \"just\nwork\" — and forgetting to **return** inside a `.then` breaks the chain (the next\nstep gets `undefined`).\n",{"id":841,"difficulty":88,"q":842,"a":843},"catch-chain","Where should you place .catch in a chain?","Usually a **single `.catch` at the end** of the chain — it handles a rejection\nfrom **any** preceding step, because errors propagate down until caught. Place an\nintermediate `.catch` only if you want to **recover** and continue the chain.\n\n```js\nstep1().then(step2).then(step3)\n  .catch(err => console.error('any step failed', err))\n\n\u002F\u002F recover mid-chain:\nload().catch(() => fallback()).then(use) \u002F\u002F continues with fallback's value\n```\n\nA `.catch` that returns a value produces a **resolved** promise, so the chain\ncontinues normally after recovery.\n",{"id":845,"difficulty":96,"q":846,"a":847},"finally-block","What does .finally do?","`.finally(cb)` runs `cb` **whether the promise fulfilled or rejected** — for\ncleanup that should always happen (hide a spinner, close a connection). It\nreceives **no argument** and, importantly, **passes the original value\u002Ferror\nthrough** unchanged.\n\n```js\nshowSpinner()\nfetchData()\n  .then(use)\n  .catch(handle)\n  .finally(() => hideSpinner()) \u002F\u002F always runs, doesn't alter the result\n```\n\nCaveat: if `.finally`'s callback itself throws or returns a rejected promise, it\n*does* override the outcome — but a normal return is ignored.\n",{"id":849,"difficulty":161,"q":850,"a":851},"unhandled-rejection","What is an unhandled promise rejection?","A rejected promise with **no `.catch`** (or no `try\u002Fcatch` around its `await`) is\n\"unhandled.\" Browsers fire an `unhandledrejection` event and log a warning; Node\nprints a warning and (in recent versions) **crashes the process** by default.\n\n```js\nPromise.reject(new Error('boom')) \u002F\u002F no handler -> unhandled rejection\n\nwindow.addEventListener('unhandledrejection', e => {\n  console.error('unhandled:', e.reason)\n  e.preventDefault()\n})\n```\n\nAlways attach a `.catch` or wrap awaits in `try\u002Fcatch`. A global handler is a\nsafety net for logging, not a substitute for handling errors at the source.\n",{"id":853,"difficulty":96,"q":854,"a":855},"resolve-reject-static","What do Promise.resolve and Promise.reject do?","They create **already-settled** promises: `Promise.resolve(v)` returns a promise\nfulfilled with `v` (or adopts `v` if it's already a promise\u002Fthenable), and\n`Promise.reject(e)` returns one rejected with `e`. Handy for returning a\nconsistent promise type or starting a chain.\n\n```js\nfunction getUser(id) {\n  const cached = cache.get(id)\n  if (cached) return Promise.resolve(cached) \u002F\u002F sync value as a promise\n  return fetch(`\u002Fapi\u002F${id}`).then(r => r.json())\n}\n```\n\n`Promise.resolve` is also how `await` wraps non-promise values, and how you\nnormalize \"maybe a value, maybe a promise\" into always-a-promise.\n",{"id":857,"difficulty":161,"q":858,"a":859},"thenable","What is a thenable?","A thenable is **any object with a `.then(resolve, reject)` method**. The promise\nmachinery treats thenables like promises — `await` and `Promise.resolve` will\n\"follow\" a thenable by calling its `then`. This is what makes different promise\nlibraries interoperate.\n\n```js\nconst thenable = {\n  then(resolve) { resolve(42) }\n}\nPromise.resolve(thenable).then(v => console.log(v)) \u002F\u002F 42\nawait thenable                                       \u002F\u002F 42\n```\n\nIt's why returning a thenable from `.then` flattens it. The downside: any object\nthat *happens* to have a `then` method gets treated specially — a rare source of\nsurprises.\n",{"id":861,"difficulty":88,"q":862,"a":863},"throw-in-then","What happens if you throw inside a .then callback?","Throwing inside a `.then` (or `.catch`) callback **rejects** the promise that\n`.then` returns, so the error skips subsequent `.then`s and is caught by the next\n`.catch` down the chain.\n\n```js\nPromise.resolve()\n  .then(() => { throw new Error('fail') })\n  .then(() => console.log('skipped'))      \u002F\u002F not run\n  .catch(err => console.log('caught:', err.message)) \u002F\u002F caught: fail\n```\n\nThis is what makes promise error handling feel like synchronous `try\u002Fcatch` — a\nthrown error propagates to the nearest handler instead of crashing.\n",{"id":865,"difficulty":88,"q":866,"a":867},"return-promise-then","What happens when you return a promise from .then?","The outer chain **waits** for that returned promise to settle and adopts its\nresult — this is \"flattening.\" It's how you sequence async steps without nesting.\n\n```js\ngetUser()\n  .then(user => fetchPosts(user.id)) \u002F\u002F returns a promise\n  .then(posts => console.log(posts)) \u002F\u002F runs only after fetchPosts resolves\n```\n\nPromises never nest as `Promise\u003CPromise\u003CT>>`; returning a promise from `.then`\nauto-unwraps it. Forgetting to **return** it, though, means the next step runs\nimmediately with `undefined`.\n",{"id":869,"difficulty":88,"q":870,"a":871},"nested-vs-flat","How do you flatten nested .then callbacks?","Nesting `.then`s recreates callback hell. Because returning a promise flattens the\nchain, you can keep it **flat** by returning instead of nesting.\n\n```js\n\u002F\u002F nested (\"promise hell\")\na().then(x => {\n  b(x).then(y => {\n    c(y).then(z => console.log(z))\n  })\n})\n\u002F\u002F flat\na().then(b).then(c).then(z => console.log(z))\n```\n\n`async\u002Fawait` flattens it even more readably. Nesting is occasionally needed when\nan inner step requires an **outer** value, but usually a flat chain (or await)\navoids it.\n",{"id":873,"difficulty":161,"q":874,"a":875},"reduce-sequential","How do you run promises sequentially using reduce?","Chain them by reducing over an array, where each step awaits the accumulator\npromise before starting — guaranteeing order and one-at-a-time execution.\n\n```js\nconst urls = ['\u002Fa', '\u002Fb', '\u002Fc']\nawait urls.reduce(\n  (chain, url) => chain.then(() => fetch(url)),\n  Promise.resolve()\n)\n\u002F\u002F or with await in a for...of:\nfor (const url of urls) await fetch(url)\n```\n\nUse this when each request must finish before the next (ordering, rate limits,\ndependencies). For independent requests, `Promise.all` is faster.\n",{"id":877,"difficulty":161,"q":878,"a":879},"concurrency-limit","How do you limit the concurrency of many async tasks?","Running thousands of requests at once with `Promise.all` can overwhelm a server\nor hit rate limits. Cap the number in flight with a **worker pool**: N workers\npulling from a shared queue.\n\n```js\nasync function pool(items, limit, fn) {\n  const results = []\n  const queue = [...items.entries()]\n  async function worker() {\n    for (const [i, item] of queue.splice(0)) results[i] = await fn(item)\n  }\n  await Promise.all(Array.from({ length: limit }, worker))\n  return results\n}\nawait pool(urls, 5, fetch) \u002F\u002F at most 5 concurrent requests\n```\n\nLibraries like `p-limit` provide this off the shelf. The idea: parallelism, but\n**bounded**.\n",{"id":881,"difficulty":161,"q":882,"a":883},"retry-backoff","How do you implement retry with exponential backoff?","Wrap the operation in a loop that catches failures and waits an increasing delay\nbefore retrying, up to a max attempt count.\n\n```js\nasync function retry(fn, attempts = 3, delay = 200) {\n  for (let i = 0; i \u003C attempts; i++) {\n    try {\n      return await fn()\n    } catch (err) {\n      if (i === attempts - 1) throw err\n      await new Promise(r => setTimeout(r, delay * 2 ** i)) \u002F\u002F 200, 400, 800...\n    }\n  }\n}\n```\n\nExponential backoff (often with jitter) avoids hammering a struggling service.\nOnly retry **idempotent**\u002Ftransient failures — retrying a non-idempotent write\ncan duplicate effects.\n",{"id":885,"difficulty":88,"q":886,"a":887},"for-await-of","What is for await...of and when do you use it?","`for await...of` iterates an **async iterable** (or an iterable of promises),\nawaiting each value in turn — ideal for consuming streams or paginated APIs\nsequentially.\n\n```js\nfor await (const chunk of readableStream) {\n  process(chunk) \u002F\u002F each chunk awaited in order\n}\n\nfor await (const value of [fetch('\u002Fa'), fetch('\u002Fb')]) {\n  console.log(value) \u002F\u002F awaits each promise sequentially\n}\n```\n\nIt processes items **one at a time** (sequential). For concurrent processing of\na fixed array, `Promise.all(arr.map(...))` is the right tool instead.\n",{"id":889,"difficulty":88,"q":890,"a":891},"top-level-await","What is top-level await?","In **ES modules**, you can use `await` at the **top level**, outside any async\nfunction. The module's evaluation pauses until the awaited promise settles, and\nimporters wait for it.\n\n```js\n\u002F\u002F config.mjs\nconst res = await fetch('\u002Fconfig.json')\nexport const config = await res.json()\n```\n\nIt's great for module initialization (loading config, dynamic imports,\nconnecting). Caveat: it can **delay** the loading of dependent modules, so avoid\nslow top-level awaits in widely-imported modules. Not available in CommonScript\nscripts.\n",{"id":893,"difficulty":161,"q":894,"a":895},"cancellation","How do you cancel a promise or async operation?","Promises themselves **can't be cancelled** — once started they run to settlement.\nThe standard approach is an **`AbortController`**: pass its `signal` to\ncancellable APIs (`fetch`, timers) and call `abort()` to stop them.\n\n```js\nconst ctrl = new AbortController()\nfetch('\u002Fslow', { signal: ctrl.signal })\n  .catch(e => { if (e.name === 'AbortError') console.log('cancelled') })\nctrl.abort() \u002F\u002F triggers an AbortError rejection\n```\n\nFor your own async functions, check `signal.aborted` at await points and bail\nout. The promise still settles (as a rejection); \"cancellation\" means stopping\nthe underlying work and ignoring the result.\n",{"id":897,"difficulty":161,"q":898,"a":899},"await-in-foreach","Why doesn't await work inside forEach?","`Array.prototype.forEach` **ignores** the return value of its callback, so it\ndoesn't await the async callback's promise — the loop fires all callbacks and\nmoves on immediately, not waiting for any of them.\n\n```js\n\u002F\u002F does NOT wait; \"done\" logs before any item is processed\nitems.forEach(async item => { await process(item) })\nconsole.log('done')\n\n\u002F\u002F sequential\nfor (const item of items) await process(item)\n\u002F\u002F concurrent\nawait Promise.all(items.map(item => process(item)))\n```\n\nUse `for...of` (sequential) or `map` + `Promise.all` (concurrent). `forEach` is\nsimply not async-aware.\n",{"id":901,"difficulty":161,"q":902,"a":903},"await-parallel-start","How do you start async tasks in parallel but await them later?","Call the async functions **first** (which starts them immediately) and store the\npromises, then `await` them afterward. The work overlaps because it began before\nany `await`.\n\n```js\nconst pa = fetchA() \u002F\u002F starts now\nconst pb = fetchB() \u002F\u002F starts now (concurrently)\nconst a = await pa  \u002F\u002F wait for both, but they already ran in parallel\nconst b = await pb\n```\n\nContrast with `const a = await fetchA(); const b = await fetchB()` which is\nsequential. `Promise.all([pa, pb])` is the cleaner equivalent and also propagates\nerrors as soon as one fails.\n",{"id":905,"difficulty":88,"q":906,"a":907},"parallel-map-all","How do you process an array concurrently with Promise.all and map?","Map each element to a promise (starting all the work), then `Promise.all` to wait\nfor the whole batch and collect results **in order**.\n\n```js\nconst results = await Promise.all(\n  ids.map(id => fetchUser(id))\n)\n\u002F\u002F results[i] corresponds to ids[i], even if they resolved out of order\n```\n\nThis runs everything concurrently — far faster than awaiting in a loop. Beware\nunbounded concurrency for large arrays (use a concurrency limit), and remember\n`Promise.all` rejects as soon as **any** task fails.\n",{"id":909,"difficulty":88,"q":910,"a":911},"explicit-construction-antipattern","What is the explicit promise construction antipattern?","Wrapping an **already-promise-returning** operation in `new Promise` is redundant,\nverbose, and easy to get wrong (forgetting to reject, swallowing errors). Just\nreturn\u002Fawait the existing promise.\n\n```js\n\u002F\u002F antipattern — wrapping a promise in a promise\nfunction load() {\n  return new Promise((resolve, reject) => {\n    fetch('\u002Fx').then(resolve).catch(reject)\n  })\n}\n\u002F\u002F just return it\nfunction load() { return fetch('\u002Fx') }\n```\n\nUse `new Promise` **only** to wrap a **callback-based** API that isn't already\npromisified.\n",{"id":913,"difficulty":88,"q":914,"a":915},"async-vs-then-style","When should you use async\u002Fawait vs .then chains?","They're interchangeable, but `async\u002Fawait` usually reads better, especially with\nbranching, loops, and try\u002Fcatch error handling. `.then` chains shine for simple\nlinear transformations and point-free style.\n\n```js\n\u002F\u002F await: clearer with logic between steps\nasync function load() {\n  const user = await getUser()\n  if (!user.active) return null\n  return getPosts(user.id)\n}\n\u002F\u002F then: fine for a straight pipeline\nconst upper = () => fetch('\u002Fx').then(r => r.text()).then(t => t.toUpperCase())\n```\n\nMixing is fine. Prefer `await` for readability; just remember every `await`\nintroduces a microtask boundary.\n",{"id":917,"difficulty":96,"q":918,"a":919},"promise-immutable","Can a promise change its state after settling?","No. A promise transitions **once** from `pending` to either `fulfilled` or\n`rejected`, and after that its state and value are **immutable**. Calling\n`resolve`\u002F`reject` again does nothing.\n\n```js\nconst p = new Promise((resolve, reject) => {\n  resolve('first')\n  resolve('second') \u002F\u002F ignored\n  reject('error')   \u002F\u002F ignored\n})\np.then(v => console.log(v)) \u002F\u002F 'first'\n```\n\nThis guarantee is what makes promises composable: once you have a settled\npromise, its result never changes, and adding more `.then`s later still gives you\nthat same value.\n",{"id":921,"difficulty":88,"q":922,"a":923},"promise-all-empty","What does Promise.all([]) resolve to?","`Promise.all([])` resolves **immediately** with an **empty array** — there's\nnothing to wait for. The same edge case applies to `allSettled([])` (empty\narray). But `Promise.any([])` **rejects** with an `AggregateError` (nothing can\nfulfill), and `Promise.race([])` stays **pending forever**.\n\n```js\nawait Promise.all([])      \u002F\u002F []\nawait Promise.allSettled([]) \u002F\u002F []\nawait Promise.race([])     \u002F\u002F never settles\n```\n\nThese empty-array behaviors are classic gotchas — guard against an empty input\nlist if it could occur, especially for `race`\u002F`any`.\n",{"id":925,"difficulty":88,"q":926,"a":927},"partial-failures","How do you handle partial failures across multiple async tasks?","Use **`Promise.allSettled`**, which waits for every task and reports each\noutcome, so one failure doesn't discard the successes (as `Promise.all` would).\n\n```js\nconst results = await Promise.allSettled(urls.map(fetch))\nconst ok = results.filter(r => r.status === 'fulfilled').map(r => r.value)\nconst failed = results.filter(r => r.status === 'rejected').map(r => r.reason)\n```\n\nThis is the right tool for dashboards, batch jobs, and \"best-effort\" operations\nwhere you want all results regardless of individual failures.\n",{"id":929,"difficulty":88,"q":930,"a":931},"fire-and-forget","What are the risks of \"fire and forget\" promises?","Calling an async function without awaiting or attaching `.catch` (\"floating\npromise\") means errors become **unhandled rejections**, and you lose control over\nordering and completion.\n\n```js\n\u002F\u002F floating — errors vanish, no way to know when it's done\nsaveAnalytics(data)\n\n\u002F\u002F at least handle errors\nsaveAnalytics(data).catch(err => log(err))\n\u002F\u002F or await if the result\u002Fordering matters\nawait saveAnalytics(data)\n```\n\nIf you intentionally don't await, **always** attach a `.catch`. Linters\n(`no-floating-promises`) flag these because silent failures are hard to debug.\n",{"id":933,"difficulty":88,"q":934,"a":935},"await-error-multiple","How do you handle errors across multiple awaits?","A single `try\u002Fcatch` around the awaits catches a rejection from **any** of them —\nexecution jumps to `catch` at the first failure, skipping the rest.\n\n```js\ntry {\n  const user = await getUser()\n  const posts = await getPosts(user.id)\n  const stats = await getStats(posts)\n} catch (err) {\n  \u002F\u002F catches whichever await rejected first\n  console.error(err)\n}\n```\n\nFor **independent** operations where you want all errors (not just the first),\nuse `Promise.allSettled` and inspect each result instead of letting the first\nrejection short-circuit.\n",{"description":86},"JavaScript promise and async\u002Fawait interview questions — states, chaining, error handling, Promise.all vs race, and converting callbacks.","javascript\u002Fasync\u002Fpromises","Promises & async\u002Fawait","qvoFc9byIt-vpMOLYR4_aXHuFSUm0hmc9QGBW5Vegyw",{"id":942,"title":943,"body":944,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":948,"navigation":91,"order":29,"path":949,"questions":950,"related":224,"seo":1047,"seoDescription":1048,"stem":1049,"subtopic":1050,"topic":55,"topicSlug":57,"updated":228,"__hash__":1051},"qa\u002Fjavascript\u002Fclasses\u002Fclass-inheritance.md","Class Inheritance",{"type":83,"value":945,"toc":946},[],{"title":86,"searchDepth":29,"depth":29,"links":947},[],{},"\u002Fjavascript\u002Fclasses\u002Fclass-inheritance",[951,955,959,963,967,971,975,979,983,987,991,995,999,1003,1007,1011,1015,1019,1023,1027,1031,1035,1039,1043],{"id":952,"difficulty":96,"q":953,"a":954},"extends-keyword","How does the extends keyword work?","`class Child extends Parent` makes `Child` inherit from `Parent`: instances get\n`Parent`'s methods via the prototype chain, and `Child` itself inherits\n`Parent`'s statics.\n\n```js\nclass Animal {\n  constructor(name) { this.name = name }\n  speak() { return `${this.name} makes a sound` }\n}\nclass Dog extends Animal {\n  speak() { return `${this.name} barks` }\n}\nnew Dog('Rex').speak()   \u002F\u002F 'Rex barks'\n```\n\n`extends` wires up two chains: `Dog.prototype -> Animal.prototype` (instance\nmethods) and `Dog -> Animal` (statics). It's the clean syntax for the manual\nprototype linking you'd otherwise write.\n",{"id":956,"difficulty":88,"q":957,"a":958},"super-constructor","What does super() do in a constructor?","It calls the **parent constructor**, initializing the inherited part of the\ninstance. In a derived class you **must** call `super()` before using `this`.\n\n```js\nclass Dog extends Animal {\n  constructor(name, breed) {\n    super(name)        \u002F\u002F run Animal's constructor first\n    this.breed = breed\n  }\n}\n```\n\nThe parent constructor actually creates `this` for a derived class, which is why\n`super()` must come first. If a subclass has no constructor, a default one\ncalls `super(...args)` automatically.\n",{"id":960,"difficulty":88,"q":961,"a":962},"super-method","How do you call a parent method with super?","`super.method()` invokes the parent class's method with the current instance as\n`this` — for extending rather than fully replacing behavior.\n\n```js\nclass Dog extends Animal {\n  speak() {\n    return super.speak() + ' (woof)'   \u002F\u002F reuse parent, add to it\n  }\n}\n```\n\n`super` works in any method, getter, or static method — not just the\nconstructor. It resolves to the method on the *parent's* prototype, so overrides\ncan build on the inherited version.\n",{"id":964,"difficulty":161,"q":965,"a":966},"this-before-super","Why does using this before super() throw?","In a derived class, the instance object is created by the parent constructor via\n`super()`. Until `super()` runs, `this` is uninitialized, so accessing it throws\na `ReferenceError`.\n\n```js\nclass Dog extends Animal {\n  constructor(name) {\n    this.x = 1     \u002F\u002F ReferenceError: must call super first\n    super(name)\n  }\n}\n```\n\nThis is a real semantic difference from constructor functions (where `this`\nexists immediately). The rule ensures the parent has fully set up the object\nbefore the child modifies it.\n",{"id":968,"difficulty":96,"q":969,"a":970},"method-overriding","What is method overriding?","Defining a method in a subclass with the same name as the parent's — the\nsubclass version shadows the parent's for instances of the subclass.\n\n```js\nclass Shape { area() { return 0 } }\nclass Circle extends Shape {\n  constructor(r) { super(); this.r = r }\n  area() { return Math.PI * this.r ** 2 }   \u002F\u002F overrides Shape.area\n}\nnew Circle(2).area()   \u002F\u002F 12.56...\n```\n\nLookup finds the subclass method first. You can still reach the parent's version\nvia `super.area()`. Overriding is the basis of polymorphism.\n",{"id":972,"difficulty":88,"q":973,"a":974},"polymorphism-js","How does polymorphism work with classes?","Different subclasses override the same method, and calling that method on a\nbase-typed reference runs the actual object's version (dynamic dispatch).\n\n```js\nclass Shape { area() { return 0 } }\nclass Circle extends Shape { area() { return Math.PI * this.r ** 2 } }\nclass Square extends Shape { area() { return this.s ** 2 } }\n\nconst shapes = [new Circle(), new Square()]\nshapes.forEach(s => console.log(s.area()))  \u002F\u002F each runs its own area()\n```\n\nJavaScript dispatches methods at runtime by the object's prototype, so a\n`Shape[]` can hold mixed subclasses and each responds with its own behavior —\nclassic polymorphism.\n",{"id":976,"difficulty":88,"q":977,"a":978},"default-constructor","What is the default constructor in a subclass?","If a subclass omits a constructor, JavaScript inserts one that forwards all\narguments to the parent: `constructor(...args) { super(...args) }`.\n\n```js\nclass Animal { constructor(name) { this.name = name } }\nclass Dog extends Animal {}        \u002F\u002F implicit: constructor(...a){ super(...a) }\nnew Dog('Rex').name                \u002F\u002F 'Rex' — forwarded to Animal\n```\n\nSo you only need to write a subclass constructor when you add fields or change\nhow the parent is called. The default just chains to `super`.\n",{"id":980,"difficulty":161,"q":981,"a":982},"super-in-static","Can you use super in static methods?","Yes — in a static method, `super.method()` calls the **parent class's** static\nmethod, because static members are inherited along the constructor's own\nprototype chain.\n\n```js\nclass Base { static create() { return 'base' } }\nclass Derived extends Base {\n  static create() { return super.create() + '-derived' }\n}\nDerived.create()   \u002F\u002F 'base-derived'\n```\n\nThis works because `Derived.__proto__ === Base`, so `super` in a static context\nresolves to `Base`. Static inheritance is a real and sometimes-surprising part\nof `extends`.\n",{"id":984,"difficulty":161,"q":985,"a":986},"extends-builtins","How do you extend built-in classes like Array or Error?","Use `extends` directly — modern engines support subclassing built-ins, with\n`super()` initializing the built-in part.\n\n```js\nclass Stack extends Array {\n  peek() { return this[this.length - 1] }\n}\nconst s = new Stack()\ns.push(1, 2); s.peek()   \u002F\u002F 2 — inherits all Array methods\n\nclass AppError extends Error {\n  constructor(msg, code) { super(msg); this.name = 'AppError'; this.code = code }\n}\n```\n\nCaveat: extending `Error` historically needed `Object.setPrototypeOf(this,\nnew.target.prototype)` for correct `instanceof` after transpilation; native\nES6+ handles it. Extending `Array` also has subtle `length`\u002Findex behaviors.\n",{"id":988,"difficulty":161,"q":989,"a":990},"abstract-class-pattern","How do you create an abstract class?","JavaScript has no `abstract` keyword, so you simulate it: throw if instantiated\ndirectly (`new.target`) and throw from methods subclasses must implement.\n\n```js\nclass Shape {\n  constructor() {\n    if (new.target === Shape) throw new Error('Shape is abstract')\n  }\n  area() { throw new Error('area() must be implemented') }\n}\nclass Circle extends Shape {\n  constructor(r) { super(); this.r = r }\n  area() { return Math.PI * this.r ** 2 }\n}\n```\n\n`new.target === Shape` blocks direct instantiation; unimplemented methods throw\nat call time. It's a convention, not a language feature.\n",{"id":992,"difficulty":88,"q":993,"a":994},"inheritance-vs-composition-class","When should you prefer composition over class inheritance?","Favor composition when behavior is orthogonal or shared across unrelated types,\nor when a deep hierarchy would become rigid. Use inheritance for genuine is-a\nrelationships with stable base classes.\n\n```js\n\u002F\u002F inheritance forcing a hierarchy\nclass FlyingSwimmingDuck extends Animal {}\n\n\u002F\u002F compose capabilities\nconst duck = { ...canFly(), ...canSwim(), name: 'Donald' }\n```\n\nDeep inheritance suffers from the fragile-base-class problem; composition (mixins,\ndelegation, functions) stays flexible. \"Favor composition over inheritance\"\napplies strongly in JS.\n",{"id":996,"difficulty":161,"q":997,"a":998},"super-property-access","Can super access parent getters and fields?","`super` accesses parent **prototype** members — methods and accessors (getters\u002F\nsetters) — but **not** instance fields (those live on `this`, not the prototype).\n\n```js\nclass A {\n  get label() { return 'A' }\n  x = 1                       \u002F\u002F instance field\n}\nclass B extends A {\n  get label() { return super.label + 'B' }  \u002F\u002F 'AB'\n  getX() { return super.x }                   \u002F\u002F undefined (field, not on proto)\n}\n```\n\nSince `super` looks up the parent prototype, it sees inherited methods\u002Faccessors\nbut not own instance fields, which belong to the instance.\n",{"id":1000,"difficulty":161,"q":1001,"a":1002},"constructor-order","What is the order of initialization in a class hierarchy?","For `new Child()`: the chain of `super()` calls runs **top-down** (parent\nconstructor first), and **fields** initialize right after that level's\n`super()` returns, before the rest of that constructor's body.\n\n```js\nclass A { constructor() { console.log('A ctor'); this.init() } init(){} }\nclass B extends A {\n  x = (console.log('B field'), 1)\n  constructor() { super(); console.log('B ctor') }\n}\n\u002F\u002F new B(): \"A ctor\" -> \"B field\" -> \"B ctor\"\n```\n\nA classic trap: a parent constructor calling an overridable method runs the\nchild override **before** the child's fields are initialized — so the override\nmay see `undefined`.\n",{"id":1004,"difficulty":88,"q":1005,"a":1006},"instanceof-hierarchy","How does instanceof behave across an inheritance hierarchy?","`instanceof` is true for the class and all its ancestors, since each ancestor's\n`prototype` is in the chain.\n\n```js\nclass A {}\nclass B extends A {}\nclass C extends B {}\nconst c = new C()\nc instanceof C   \u002F\u002F true\nc instanceof B   \u002F\u002F true\nc instanceof A   \u002F\u002F true\n```\n\nSo `instanceof` answers \"is-a (or descends-from)\". To check the *exact* class,\ncompare `obj.constructor === C` or `Object.getPrototypeOf(obj) === C.prototype`.\n",{"id":1008,"difficulty":161,"q":1009,"a":1010},"mixin-with-extends","How do you achieve multiple inheritance with classes?","JavaScript allows only single `extends`, so you simulate multiple inheritance\nwith **mixins** — functions that take a base class and return an extended one,\nchained together.\n\n```js\nconst Serializable = (B) => class extends B { serialize() {} }\nconst Comparable  = (B) => class extends B { compareTo() {} }\n\nclass Model extends Serializable(Comparable(Object)) {}\n```\n\nEach mixin wraps the previous class, building a linear chain that combines\nbehaviors. This is the standard pattern for \"implementing multiple interfaces\"\nof behavior in JS.\n",{"id":1012,"difficulty":161,"q":1013,"a":1014},"super-this-binding","What is this when calling super.method()?","`this` stays the **current instance** — `super.method()` runs the parent's\nmethod but with the child instance as `this`, so it operates on the child's data.\n\n```js\nclass A { describe() { return this.constructor.name } }\nclass B extends A {\n  describe() { return super.describe() }   \u002F\u002F parent method, child `this`\n}\nnew B().describe()   \u002F\u002F 'B' — this.constructor is B\n```\n\n`super` changes *which method* runs, not the receiver. That's why an inherited\nmethod can still see the subclass's overridden properties and constructor.\n",{"id":1016,"difficulty":161,"q":1017,"a":1018},"overriding-getter","How do you override a getter or setter in a subclass?","Redefine the accessor in the subclass. Note that defining only a getter (or only\na setter) in the child can **hide** the inherited pair, so redefine both if\nneeded.\n\n```js\nclass A {\n  get value() { return 1 }\n  set value(v) {}\n}\nclass B extends A {\n  get value() { return super.value + 1 }   \u002F\u002F extend\n  \u002F\u002F if you define only the getter, the inherited setter is shadowed away\n}\n```\n\nAccessors are properties, so overriding one member of a get\u002Fset pair replaces\nthe whole property descriptor — define both in the child to keep both behaviors.\n",{"id":1020,"difficulty":88,"q":1021,"a":1022},"protected-convention","Does JavaScript have protected members?","No `protected` keyword. The conventions are: `_underscore` (a hint that it's\n\"internal,\" not enforced) or `#private` (truly private, but **not** accessible\nto subclasses).\n\n```js\nclass Base {\n  _internal = 1   \u002F\u002F convention: subclasses may use, but not enforced\n  #secret = 2     \u002F\u002F private — subclasses CANNOT access this\n}\n```\n\n`#private` is stricter than protected (even subclasses can't see it). For\nsubclass-accessible-but-not-public members, the `_` convention is all JS offers.\n",{"id":1024,"difficulty":161,"q":1025,"a":1026},"calling-overridden-from-parent","Can a parent method call a method overridden by the child?","Yes — method dispatch is dynamic, so a parent method calling `this.foo()` runs\nthe **child's** override if there is one. This is the template-method pattern.\n\n```js\nclass Base {\n  process() { return this.transform(this.read()) }  \u002F\u002F calls overrides\n  read() { return 'data' }\n  transform(x) { return x }\n}\nclass Json extends Base {\n  transform(x) { return JSON.parse(x) }   \u002F\u002F parent's process() uses this\n}\n```\n\nBecause `this` is the actual instance, the inherited `process()` polymorphically\ninvokes the subclass's `transform` — powerful, but watch the constructor-order\ntrap.\n",{"id":1028,"difficulty":161,"q":1029,"a":1030},"super-not-in-arrow","How does super behave inside an arrow function in a method?","An arrow function lexically captures `super` from its enclosing method, so\n`super.x` works inside an arrow defined within a method.\n\n```js\nclass B extends A {\n  greet() {\n    const fn = () => super.greet()   \u002F\u002F super captured lexically\n    return fn()\n  }\n}\n```\n\nLike `this`, `super` is lexical in arrows — it binds to where the arrow is\nwritten. A regular nested function, by contrast, has no `super` binding.\n",{"id":1032,"difficulty":161,"q":1033,"a":1034},"extends-null","What does extends null do?","`class C extends null` creates a class whose instances do **not** inherit from\n`Object.prototype` — like `Object.create(null)` but as a class. It's an edge case\nand tricky (you must manually handle the prototype in the constructor).\n\n```js\nclass NullProto extends null {\n  constructor() { return Object.create(new.target.prototype) }\n}\n```\n\nInstances lack `toString`, `hasOwnProperty`, etc. It's rarely used — mainly for\ncreating prototype-less objects via class syntax. Most code never needs it.\n",{"id":1036,"difficulty":88,"q":1037,"a":1038},"refactor-function-to-class","What changes when refactoring a constructor function to a class?","Mostly cosmetic, but watch the behavioral differences: classes **must** be called\nwith `new`, are **not usable before declaration** (TDZ), run in **strict mode**,\nand have **non-enumerable** methods.\n\n```js\n\u002F\u002F these worked with the function but not the class:\nconst f = MyFunc()        \u002F\u002F -> class: TypeError (needs new)\nnew MyClassUsedAbove()    \u002F\u002F -> ReferenceError (TDZ) if used before declaration\n```\n\nSo code that relied on calling without `new`, hoisting, or sloppy-mode behavior\ncan break. The upside is those were usually bugs the class now catches.\n",{"id":1040,"difficulty":88,"q":1041,"a":1042},"super-multiple-levels","How does super work across multiple inheritance levels?","Each class's `super` refers to its **immediate** parent, so a method can be\nextended at each level and chained via `super`.\n\n```js\nclass A { greet() { return 'A' } }\nclass B extends A { greet() { return super.greet() + 'B' } }\nclass C extends B { greet() { return super.greet() + 'C' } }\nnew C().greet()   \u002F\u002F 'ABC'\n```\n\n`super` is statically bound to the class where the method is defined (its\n`[[HomeObject]]`), not the runtime instance — so multi-level chains resolve\ncorrectly even with overrides.\n",{"id":1044,"difficulty":88,"q":1045,"a":1046},"composition-via-fields","How do you compose behavior by holding instances (has-a)?","Instead of inheriting, a class can **hold** another object and delegate to it —\ncomposition over inheritance.\n\n```js\nclass Engine { start() { return 'vroom' } }\nclass Car {\n  #engine = new Engine()              \u002F\u002F has-a Engine\n  start() { return this.#engine.start() }  \u002F\u002F delegate\n}\n```\n\nThis avoids tight coupling to a base class and lets you swap the held object.\nMany designs that look like inheritance are cleaner as composition with\ndelegation.\n",{"description":86},"JavaScript class inheritance interview questions — extends, super, overriding, constructor chaining, polymorphism and extending built-ins.","javascript\u002Fclasses\u002Fclass-inheritance","Inheritance with extends & super","WkrLqBmf4KArV2-vQoIEAb1a75wOTEM9nf9RxS4CGW4",{"id":1053,"title":1054,"body":1055,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":1059,"navigation":91,"order":11,"path":1060,"questions":1061,"related":224,"seo":1166,"seoDescription":1167,"stem":1168,"subtopic":1169,"topic":55,"topicSlug":57,"updated":228,"__hash__":1170},"qa\u002Fjavascript\u002Fclasses\u002Fclass-syntax.md","Class Syntax",{"type":83,"value":1056,"toc":1057},[],{"title":86,"searchDepth":29,"depth":29,"links":1058},[],{},"\u002Fjavascript\u002Fclasses\u002Fclass-syntax",[1062,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,1106,1110,1114,1118,1122,1126,1130,1134,1138,1142,1146,1150,1154,1158,1162],{"id":1063,"difficulty":96,"q":1064,"a":1065},"what-is-class","What is a class in JavaScript?","A `class` is a template for creating objects — syntactic sugar over constructor\nfunctions and prototypes that gives a cleaner, more familiar OOP syntax.\n\n```js\nclass User {\n  constructor(name) { this.name = name }\n  greet() { return `Hi, ${this.name}` }\n}\nconst u = new User('Ada')\nu.greet()  \u002F\u002F 'Hi, Ada'\n```\n\nUnder the hood, `User` is a function, `greet` lives on `User.prototype`, and\n`new User()` does the usual prototype wiring. Classes add conveniences (strict\nmode, `new`-only, non-enumerable methods) but use the same prototypal machinery.\n",{"id":1067,"difficulty":88,"q":1068,"a":1069},"class-vs-function","How do classes differ from constructor functions?","Classes are functions with extra rules:\n\n- **Must be called with `new`** (throw otherwise).\n- **Always strict mode** inside the body.\n- **Methods are non-enumerable** (won't show in `for...in`).\n- **Not hoisted** for use (temporal dead zone).\n- Built-in `extends`\u002F`super` for inheritance.\n\n```js\nclass C {}\nC()        \u002F\u002F TypeError: Class constructor cannot be invoked without 'new'\nfunction F() {}\nF()        \u002F\u002F fine (no error)\n```\n\nThey're the same prototype mechanism with safer defaults and nicer syntax. The\n`new`-enforcement alone eliminates the classic \"forgot new\" bug.\n",{"id":1071,"difficulty":96,"q":1072,"a":1073},"constructor-method","What is the constructor method?","A special method that runs when an instance is created with `new`, used to\ninitialize instance properties. A class can have **at most one**.\n\n```js\nclass Point {\n  constructor(x, y) {\n    this.x = x\n    this.y = y\n  }\n}\n```\n\nIf you omit it, JavaScript supplies a default empty one (or one that calls\n`super(...args)` in a subclass). The constructor is where per-instance state on\n`this` is set up.\n",{"id":1075,"difficulty":88,"q":1076,"a":1077},"class-methods-prototype","Where do class methods live?","Regular methods are defined on the class's **`prototype`**, so all instances\nshare one copy.\n\n```js\nclass User { greet() {} }\nUser.prototype.greet           \u002F\u002F the method\nconst a = new User(), b = new User()\na.greet === b.greet            \u002F\u002F true — shared\n```\n\nThis is memory-efficient. Class fields and arrow-function fields, by contrast,\nare created **per instance** (on `this`), not on the prototype — an important\ndistinction.\n",{"id":1079,"difficulty":88,"q":1080,"a":1081},"class-fields","What are class fields?","Class fields (public instance fields) let you declare instance properties\ndirectly in the class body, initialized per instance before the constructor body\nruns.\n\n```js\nclass Counter {\n  count = 0               \u002F\u002F instance field\n  step = 1\n  constructor(step) { if (step) this.step = step }\n}\n```\n\nFields are added to each instance (on `this`), not the prototype. They're handy\nfor default values and for arrow-function methods that bind `this`. Each\ninstance gets its own copy.\n",{"id":1083,"difficulty":161,"q":1084,"a":1085},"arrow-class-field","What is the difference between a method and an arrow-function field?","A **method** lives on the prototype (shared) and gets its `this` from the call\nsite. An **arrow-function field** is created per instance and captures `this`\nlexically (bound to the instance) — useful for callbacks.\n\n```js\nclass Btn {\n  label = 'Click'\n  handleA() { return this.label }       \u002F\u002F prototype method — `this` can be lost\n  handleB = () => this.label             \u002F\u002F instance arrow — `this` always bound\n}\nconst b = new Btn()\nconst a = b.handleA; a()   \u002F\u002F this is undefined\nconst c = b.handleB; c()   \u002F\u002F 'Click'\n```\n\nArrow fields cost memory (one per instance) but solve the \"lost `this`\" problem\nfor event handlers without manual `bind`.\n",{"id":1087,"difficulty":88,"q":1088,"a":1089},"class-expression","What is a class expression?","A class defined as an expression (assigned to a variable or passed around),\noptionally named. Mirrors function declarations vs expressions.\n\n```js\nconst User = class { greet() {} }          \u002F\u002F anonymous class expression\nconst Animal = class Named {                \u002F\u002F named (name visible inside only)\n  whoAmI() { return Named.name }\n}\n```\n\nClass expressions are useful for conditionally creating classes, mixins (a\nfunction returning a class), and IIFE-style patterns. Like function expressions,\nthe name in a named class expression is scoped to the class body.\n",{"id":1091,"difficulty":88,"q":1092,"a":1093},"class-hoisting","Are classes hoisted?","Class declarations are hoisted but remain in the **temporal dead zone**, so you\n**can't use them before** their declaration — unlike function declarations.\n\n```js\nnew Foo()   \u002F\u002F ReferenceError: Cannot access 'Foo' before initialization\nclass Foo {}\n```\n\nSo practically, classes behave as \"not hoisted.\" Always declare a class before\ninstantiating or extending it. This is one behavioral difference from converting\na constructor function to a class.\n",{"id":1095,"difficulty":96,"q":1096,"a":1097},"method-shorthand","How do you define different kinds of methods in a class?","The class body supports several method forms:\n\n```js\nclass Example {\n  regular() {}                 \u002F\u002F prototype method\n  static helper() {}           \u002F\u002F on the class itself\n  get value() {}               \u002F\u002F getter\n  set value(v) {}              \u002F\u002F setter\n  async load() {}              \u002F\u002F async method\n  *generate() {}               \u002F\u002F generator method\n  [Symbol.iterator]() {}       \u002F\u002F computed\u002Fsymbol method\n}\n```\n\nAll of these (except fields) go on the prototype (or the class for `static`).\nThe class body is its own syntax — no commas between members, always strict.\n",{"id":1099,"difficulty":88,"q":1100,"a":1101},"getters-setters-class","How do getters and setters work in classes?","`get`\u002F`set` define accessor properties on the prototype that run on read\u002Fwrite,\nso a property can be computed or validated.\n\n```js\nclass Temperature {\n  #celsius = 0\n  get celsius() { return this.#celsius }\n  set celsius(v) {\n    if (typeof v !== 'number') throw new TypeError('number required')\n    this.#celsius = v\n  }\n  get fahrenheit() { return this.#celsius * 1.8 + 32 }\n}\n```\n\nAccessors let you expose a clean property API while validating or deriving\nbehind the scenes. A getter without a setter makes a read-only property.\n",{"id":1103,"difficulty":88,"q":1104,"a":1105},"static-method","What is a static method?","A method on the **class itself**, not on instances — called as `ClassName.method()`.\n`this` inside it is the class.\n\n```js\nclass MathUtil {\n  static square(n) { return n * n }\n}\nMathUtil.square(4)   \u002F\u002F 16\nnew MathUtil().square \u002F\u002F undefined — not on instances\n```\n\nStatics are for utilities and factory methods that don't need instance state\n(`Array.from`, `Object.keys`, `User.fromJSON`). They're inherited by subclasses\nvia the class's own prototype chain.\n",{"id":1107,"difficulty":88,"q":1108,"a":1109},"this-in-class-method","What is this in a class method, and how can it be lost?","In a method called as `instance.method()`, `this` is the instance. Because class\nbodies are strict, extracting the method gives `this === undefined` (a\n`TypeError`), not the global object.\n\n```js\nclass Counter {\n  count = 0\n  inc() { this.count++ }\n}\nconst c = new Counter()\nconst fn = c.inc\nfn()   \u002F\u002F TypeError: Cannot read properties of undefined\n```\n\nFixes: call it on the instance (`() => c.inc()`), `bind` it, or use an\narrow-function field. This is the React class-component `this` problem.\n",{"id":1111,"difficulty":96,"q":1112,"a":1113},"class-vs-object-literal","When should you use a class vs an object literal?","Use a **class** when you need many instances with shared behavior, inheritance,\nor encapsulated state. Use an **object literal** for a single, fixed\nconfiguration or namespace.\n\n```js\nconst config = { apiUrl: '\u002Fapi', timeout: 5000 }   \u002F\u002F one-off -> literal\nclass User { constructor(name) { this.name = name } }  \u002F\u002F many instances -> class\n```\n\nDon't reach for a class just to group functions — a module or plain object is\nsimpler. Classes shine when you're modeling entities that come in multiples.\n",{"id":1115,"difficulty":96,"q":1116,"a":1117},"instanceof-class","How do you check if an object is an instance of a class?","Use `instanceof`, which checks whether the class's `prototype` is in the\nobject's prototype chain (so it sees inheritance).\n\n```js\nclass Animal {}\nclass Dog extends Animal {}\nconst d = new Dog()\nd instanceof Dog     \u002F\u002F true\nd instanceof Animal  \u002F\u002F true (ancestor)\n```\n\nFor cross-realm safety or duck typing, `instanceof` can be unreliable;\n`Symbol.hasInstance` can customize it, and feature checks\n(`typeof obj.bark === 'function'`) are an alternative.\n",{"id":1119,"difficulty":88,"q":1120,"a":1121},"tostring-class","How do you customize how a class instance prints?","Override `toString` (and optionally `Symbol.toPrimitive`) to control string\nconversion in concatenation, template literals, and logging.\n\n```js\nclass Money {\n  constructor(cents) { this.cents = cents }\n  toString() { return `$${(this.cents \u002F 100).toFixed(2)}` }\n}\n`${new Money(150)}`   \u002F\u002F '$1.50'\n```\n\nWithout it, instances stringify to `[object Object]`. For richer debug output in\nNode, you can also implement `[Symbol.for('nodejs.util.inspect.custom')]`.\n",{"id":1123,"difficulty":88,"q":1124,"a":1125},"class-strict-mode","Why are class bodies always in strict mode?","The spec runs all class code in strict mode automatically — no `'use strict'`\nneeded. This surfaces bugs (e.g. `this` is `undefined` in detached methods\ninstead of the global object) and disallows sloppy-mode footguns.\n\n```js\nclass C {\n  m() {\n    undeclared = 1   \u002F\u002F ReferenceError (strict)\n    return this      \u002F\u002F undefined when called without a receiver\n  }\n}\n```\n\nStrict mode is part of what makes classes safer than constructor functions: many\nmistakes throw loudly instead of failing silently.\n",{"id":1127,"difficulty":88,"q":1128,"a":1129},"computed-method-names","Can class method names be computed?","Yes — use `[expression]` for dynamic method names, including well-known symbols.\n\n```js\nconst methodName = 'greet'\nclass User {\n  [methodName]() { return 'hi' }            \u002F\u002F dynamic name\n  [Symbol.iterator]() { \u002F* ... *\u002F }          \u002F\u002F symbol method\n}\nnew User().greet()   \u002F\u002F 'hi'\n```\n\nComputed names enable symbol-keyed methods (making a class iterable, thenable,\netc.) and metaprogramming where method names come from data.\n",{"id":1131,"difficulty":161,"q":1132,"a":1133},"class-field-vs-constructor-assign","What is the difference between a class field and assigning in the constructor?","They're largely equivalent, but timing and inheritance differ. A class field\ninitializes **after `super()`** but **before** the rest of a subclass\nconstructor body; constructor assignment happens wherever you write it.\n\n```js\nclass A {\n  x = 1               \u002F\u002F field\n  constructor() { this.y = 2 }  \u002F\u002F constructor assignment\n}\n```\n\nA subtle gotcha: in a subclass, parent constructor logic runs before the child's\n**fields** are initialized, so a parent method called during construction won't\nsee the child's field values yet.\n",{"id":1135,"difficulty":88,"q":1136,"a":1137},"private-methods-intro","Can classes have private members?","Yes — prefix with `#` for truly private fields and methods, accessible only\ninside the class.\n\n```js\nclass Account {\n  #balance = 0\n  #log(msg) { \u002F* private method *\u002F }\n  deposit(n) { this.#balance += n; this.#log('deposit') }\n  get balance() { return this.#balance }\n}\nnew Account().#balance   \u002F\u002F SyntaxError — private outside class\n```\n\nUnlike the old `_underscore` convention (just a hint), `#private` is enforced by\nthe language. (Covered in depth in the static & private members topic.)\n",{"id":1139,"difficulty":88,"q":1140,"a":1141},"super-call-method","How do you call a parent method from a subclass?","Use `super.method()` inside the subclass — it invokes the parent's version with\nthe current instance as `this`.\n\n```js\nclass Animal { speak() { return 'sound' } }\nclass Dog extends Animal {\n  speak() { return super.speak() + ': woof' }  \u002F\u002F extend, don't replace\n}\nnew Dog().speak()   \u002F\u002F 'sound: woof'\n```\n\n`super` works in any method (not just the constructor) and is the clean\nreplacement for the manual `Parent.prototype.method.call(this)` pattern.\n",{"id":1143,"difficulty":161,"q":1144,"a":1145},"returning-from-class-constructor","Can a class constructor return a value?","Like constructor functions, returning an **object** overrides the instance;\nreturning a primitive is ignored. But in a **derived** class you can only return\nan object or `undefined`.\n\n```js\nclass A { constructor() { return { custom: true } } }\nnew A()   \u002F\u002F { custom: true }\n\nclass B extends A { constructor() { super(); return 5 } } \u002F\u002F 5 ignored -> instance\n```\n\nThis enables caching\u002Fsingleton tricks but is rarely needed and easy to misuse.\nMost constructors should return nothing.\n",{"id":1147,"difficulty":161,"q":1148,"a":1149},"class-toStringTag","How do you change the [object X] tag of a class?","Define a `Symbol.toStringTag` getter to control what\n`Object.prototype.toString.call(instance)` reports.\n\n```js\nclass Collection {\n  get [Symbol.toStringTag]() { return 'Collection' }\n}\nObject.prototype.toString.call(new Collection())\n\u002F\u002F '[object Collection]'\n```\n\nThis affects the default `toString` tag and some debugging output. It's a niche\nfeature, mostly used by built-ins (`Map`, `Promise`) and libraries that want\nmeaningful type tags.\n",{"id":1151,"difficulty":161,"q":1152,"a":1153},"extends-expression","Can you extend an expression, not just a class name?","Yes — `extends` accepts any expression that evaluates to a constructor (or\n`null`). This enables **mixin factories** and dynamic base classes.\n\n```js\nconst Serializable = (Base) => class extends Base {\n  toJSON() { return { ...this } }\n}\nclass Model extends Serializable(Object) {}\n```\n\nBecause `extends \u003Cexpr>` is evaluated, you can compute the superclass — the basis\nof the mixin-via-class-factory pattern. `extends null` creates a class with no\n`Object.prototype` (advanced\u002Frare).\n",{"id":1155,"difficulty":96,"q":1156,"a":1157},"method-chaining-class","How do you enable fluent method chaining in a class?","Return `this` from methods so calls chain on the same instance.\n\n```js\nclass Builder {\n  parts = []\n  add(p) { this.parts.push(p); return this }\n  build() { return this.parts.join('') }\n}\nnew Builder().add('a').add('b').build()   \u002F\u002F 'ab'\n```\n\nReturning the instance is the builder\u002Ffluent pattern, common in query builders\nand configuration APIs. Each method does its work and hands back `this`.\n",{"id":1159,"difficulty":88,"q":1160,"a":1161},"class-pitfall-this-callback","Why do class methods passed as callbacks lose this?","Passing `instance.method` as a callback detaches it from the instance; when the\ncaller invokes it plainly, strict-mode `this` is `undefined`.\n\n```js\nclass Timer {\n  seconds = 0\n  tick() { this.seconds++ }   \u002F\u002F `this` lost if passed directly\n  start() {\n    setInterval(this.tick, 1000)        \u002F\u002F this is undefined\n    setInterval(() => this.tick(), 1000) \u002F\u002F arrow keeps this\n  }\n}\n```\n\nFix with an arrow wrapper, `.bind(this)`, or an arrow-function class field. This\nis the single most common class `this` bug.\n",{"id":1163,"difficulty":88,"q":1164,"a":1165},"when-not-class","When should you avoid classes?","Avoid classes when there's no real instance state or behavior to model — a\nmodule of functions or a plain object is simpler and more idiomatic in JS.\n\n```js\n\u002F\u002F class just to namespace stateless functions\nclass StringUtils { static reverse(s) { return [...s].reverse().join('') } }\n\n\u002F\u002F plain functions \u002F module\nexport const reverse = (s) => [...s].reverse().join('')\n```\n\nFunctional and composition-based code often reads better in JavaScript than\nclass hierarchies. Use classes for genuine entities with state + behavior +\n(sometimes) inheritance — not as a default container.\n",{"description":86},"JavaScript class interview questions — class syntax, constructors, methods, fields, classes vs constructor functions, hoisting and common gotchas.","javascript\u002Fclasses\u002Fclass-syntax","Class Syntax & Methods","nrOdp4po-2N3gRIW5xxIV4MrZLoT1Apgk_BkUHFZq_0",{"id":1172,"title":1173,"body":1174,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":1178,"navigation":91,"order":47,"path":1179,"questions":1180,"related":224,"seo":1273,"seoDescription":1274,"stem":1275,"subtopic":1276,"topic":55,"topicSlug":57,"updated":228,"__hash__":1277},"qa\u002Fjavascript\u002Fclasses\u002Fmixins-composition.md","Mixins Composition",{"type":83,"value":1175,"toc":1176},[],{"title":86,"searchDepth":29,"depth":29,"links":1177},[],{},"\u002Fjavascript\u002Fclasses\u002Fmixins-composition",[1181,1185,1189,1193,1197,1201,1205,1209,1213,1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269],{"id":1182,"difficulty":88,"q":1183,"a":1184},"what-is-mixin","What is a mixin?","A mixin is a reusable bundle of methods that can be added to multiple classes or\nobjects without using inheritance — a way to share behavior across unrelated\ntypes.\n\n```js\nconst serializable = {\n  serialize() { return JSON.stringify(this) },\n}\nclass User {}\nObject.assign(User.prototype, serializable)  \u002F\u002F mix in\nnew User().serialize()\n```\n\nMixins solve \"I need this capability in several classes that don't share a common\nparent.\" They're JavaScript's answer to multiple inheritance and interface-style\nsharing.\n",{"id":1186,"difficulty":88,"q":1187,"a":1188},"object-assign-mixin","How do you implement a mixin with Object.assign?","Copy the mixin's methods onto a class's prototype (shared) or onto an instance.\n\n```js\nconst canFly = { fly() { return `${this.name} flies` } }\nconst canSwim = { swim() { return `${this.name} swims` } }\n\nclass Duck { constructor(name) { this.name = name } }\nObject.assign(Duck.prototype, canFly, canSwim)\n\nconst d = new Duck('Donald')\nd.fly(); d.swim()\n```\n\n`Object.assign(Class.prototype, ...mixins)` adds the methods once for all\ninstances. The mixin methods use `this`, so they operate on whatever object they\nend up on.\n",{"id":1190,"difficulty":161,"q":1191,"a":1192},"mixin-factory","What is a mixin factory (subclass factory)?","A function that takes a base class and returns a new class extending it with\nadded behavior — composable via nesting.\n\n```js\nconst Timestamped = (Base) => class extends Base {\n  constructor(...args) { super(...args); this.createdAt = Date.now() }\n}\nconst Serializable = (Base) => class extends Base {\n  toJSON() { return { ...this } }\n}\nclass Model extends Timestamped(Serializable(Object)) {}\n```\n\nEach factory wraps the previous class, building a linear chain that combines\nfeatures — the idiomatic modern mixin pattern, since it works with `super` and\n`extends`.\n",{"id":1194,"difficulty":88,"q":1195,"a":1196},"composition-over-inheritance","What does \"favor composition over inheritance\" mean?","Build objects by **combining small, focused pieces** (functions, mixins, held\nobjects) rather than inheriting from a deep class hierarchy — more flexible and\nless coupled.\n\n```js\n\u002F\u002F inheritance: rigid hierarchy\nclass Robot extends Machine {}\n\n\u002F\u002F composition: assemble capabilities\nconst robot = { ...withPower(), ...withMovement(), ...withSensors() }\n```\n\nInheritance locks a type into one hierarchy and suffers the fragile-base-class\nproblem. Composition lets you mix exactly the behaviors needed and swap them\nindependently. It's a core OO design principle, especially apt in JS.\n",{"id":1198,"difficulty":88,"q":1199,"a":1200},"functional-composition","What is functional composition?","Combining simple functions so the output of one feeds the next, building complex\nbehavior from small reusable parts.\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 process = pipe(trim, toLowerCase, removeSpaces)\nprocess('  Hello World ')   \u002F\u002F 'helloworld'\n```\n\n`compose` applies right-to-left, `pipe` left-to-right. Function composition is\nthe functional-programming counterpart to object composition — assemble behavior\nfrom tiny, testable units.\n",{"id":1202,"difficulty":88,"q":1203,"a":1204},"duck-typing","What is duck typing?","\"If it walks like a duck and quacks like a duck, it's a duck\" — judging an object\nby whether it has the needed methods\u002Fproperties, not by its class.\n\n```js\nfunction makeItQuack(thing) {\n  if (typeof thing.quack === 'function') return thing.quack()\n  throw new Error('not quackable')\n}\n```\n\nJavaScript leans heavily on duck typing: code checks for capabilities\n(`typeof x.then === 'function'` for thenables) rather than `instanceof`. It pairs\nnaturally with composition and mixins, where behavior matters more than lineage.\n",{"id":1206,"difficulty":88,"q":1207,"a":1208},"mixin-vs-inheritance","When do you use a mixin instead of inheritance?","Use a mixin when a capability is shared by **unrelated** classes, or when a class\nneeds behaviors from **multiple** sources (which single inheritance can't\nprovide).\n\n```js\n\u002F\u002F both need serialization, but aren't otherwise related\nObject.assign(User.prototype, Serializable)\nObject.assign(Invoice.prototype, Serializable)\n```\n\nUse inheritance for a genuine is-a relationship with a single, stable parent. If\nyou find yourself wanting to extend two parents, that's a mixin (or composition)\nsituation.\n",{"id":1210,"difficulty":161,"q":1211,"a":1212},"mixin-conflicts","What happens when two mixins define the same method?","With `Object.assign`, the **last** mixin wins silently — no error, the earlier\nmethod is overwritten.\n\n```js\nconst a = { run() { return 'a' } }\nconst b = { run() { return 'b' } }\nObject.assign(target, a, b)\ntarget.run()   \u002F\u002F 'b' — collision resolved by order, silently\n```\n\nYou must manage conflicts yourself: rename methods, namespace them, or resolve\nexplicitly. This is the trade-off mixins make for flexibility — no automatic\nconflict detection like some languages' traits.\n",{"id":1214,"difficulty":161,"q":1215,"a":1216},"stateful-mixins","How do mixins handle state?","Method-only mixins are simplest. For state, use a **mixin factory** (so it can run\nconstructor logic via `super`) or initialize state in the mixin's methods —\nobject-literal mixins can't easily set up per-instance fields.\n\n```js\nconst Counter = (Base) => class extends Base {\n  #count = 0\n  increment() { return ++this.#count }\n}\nclass Widget extends Counter(Object) {}\n```\n\nThe class-factory form integrates with the constructor chain, so it can declare\nfields and call `super()`. Plain `Object.assign` mixins are best for stateless\nbehavior.\n",{"id":1218,"difficulty":88,"q":1219,"a":1220},"delegation","What is delegation as a composition technique?","Holding another object and **forwarding** calls to it (has-a), instead of\ninheriting — a flexible alternative to subclassing.\n\n```js\nclass Engine { start() { return 'vroom' } }\nclass Car {\n  #engine = new Engine()\n  start() { return this.#engine.start() }   \u002F\u002F delegate\n}\n```\n\nDelegation lets you swap the held object, compose multiple collaborators, and\navoid tight base-class coupling. It's the runtime sibling of prototypal\ndelegation, done explicitly with object fields.\n",{"id":1222,"difficulty":161,"q":1223,"a":1224},"traits","What are \"traits\" and how do they differ from mixins?","Traits are like mixins but with stricter conflict handling — they require explicit\nresolution when methods clash, rather than silently overwriting. JavaScript has no\nbuilt-in traits; libraries emulate them.\n\n```js\n\u002F\u002F emulated trait: throw on conflict instead of silent override\nfunction applyTrait(target, trait) {\n  for (const k of Object.keys(trait)) {\n    if (k in target) throw new Error(`conflict: ${k}`)\n    target[k] = trait[k]\n  }\n}\n```\n\nThe distinction is mostly academic in JS — both share behavior horizontally; the\ndifference is conflict policy. Plain `Object.assign` mixins are the common\nreality.\n",{"id":1226,"difficulty":88,"q":1227,"a":1228},"react-hooks-composition","How is composition used outside of classes?","Modern JS increasingly composes **functions** rather than objects — e.g. React\nhooks, higher-order functions, and middleware pipelines all build behavior by\ncombining functions.\n\n```js\n\u002F\u002F composing custom hooks (function composition of behavior)\nfunction useUser(id) {\n  const data = useFetch(`\u002Fusers\u002F${id}`)\n  const auth = useAuth()\n  return { ...data, isOwner: auth.id === id }\n}\n```\n\nThe trend in JS is away from class hierarchies toward composing small functions\nand objects. Understanding composition matters even if you rarely write classes.\n",{"id":1230,"difficulty":161,"q":1231,"a":1232},"mixin-super","Can a mixin call the base class's method?","Yes — if it's a **class-factory mixin**, it can use `super.method()` to call the\nwrapped base class, enabling cooperative behavior.\n\n```js\nconst Loud = (Base) => class extends Base {\n  speak() { return super.speak().toUpperCase() }  \u002F\u002F augments base\n}\nclass Animal { speak() { return 'hi' } }\nclass Dog extends Loud(Animal) {}\nnew Dog().speak()   \u002F\u002F 'HI'\n```\n\nObject-literal mixins can't use `super` (no base class), but class-factory mixins\nsit in the prototype chain, so `super` works — letting mixins decorate inherited\nmethods.\n",{"id":1234,"difficulty":88,"q":1235,"a":1236},"object-composition-pattern","How do you compose objects with factory functions?","Build an object by spreading capability objects into it — each capability is a\nsmall factory that closes over shared state.\n\n```js\nconst hasName = (name) => ({ getName: () => name })\nconst canGreet = (self) => ({ greet: () => `Hi, ${self.getName()}` })\n\nfunction createPerson(name) {\n  const self = { ...hasName(name) }\n  return { ...self, ...canGreet(self) }\n}\n```\n\nThis factory-composition style avoids `class`\u002F`this`\u002F`new` entirely, assembling\nbehavior from functions. It's popular in functional-leaning JS codebases.\n",{"id":1238,"difficulty":88,"q":1239,"a":1240},"interface-segregation-js","How do mixins relate to interfaces?","JavaScript has no `interface` keyword, but mixins act like **implementable\ninterfaces of behavior** — a class can \"implement\" several capabilities by mixing\nthem in, similar to implementing multiple interfaces.\n\n```js\nclass FileLogger extends Loggable(Serializable(Object)) {}\n\u002F\u002F \"implements\" Loggable and Serializable behaviors\n```\n\nWhere a typed language declares `implements A, B`, JS mixes the actual behavior\nin. (TypeScript adds real `interface`\u002F`implements` on top for type checking.)\n",{"id":1242,"difficulty":88,"q":1243,"a":1244},"avoid-deep-hierarchy","What problems come from deep inheritance hierarchies?","Deep hierarchies cause the **fragile base class** problem (a base change breaks\nfar-off subclasses), tight coupling, rigidity (a type is stuck in one tree), and\n\"yo-yo\" debugging across many levels.\n\n```js\n\u002F\u002F hard to change Animal without risking Dog, Puppy, ServiceDog, ...\nclass ServiceDog extends Puppy extends Dog extends Animal {}\n```\n\nFlatten with composition: give objects the behaviors they need from small mixins\u002F\ncollaborators instead of inheriting a long chain. Two or three levels is usually\na practical ceiling.\n",{"id":1246,"difficulty":88,"q":1247,"a":1248},"composition-testing","Why is composition easier to test than inheritance?","Composed pieces are small, independent units you can test in isolation and swap\nwith fakes. Inheritance ties behavior to a hierarchy, so testing a subclass drags\nin the whole base.\n\n```js\nclass Order {\n  constructor(payment) { this.payment = payment }   \u002F\u002F injected collaborator\n  checkout() { return this.payment.charge() }\n}\nnew Order({ charge: () => 'mock' }).checkout()   \u002F\u002F easy to fake\n```\n\nDependency injection + composition lets you substitute collaborators in tests.\nThat testability is a major reason \"composition over inheritance\" holds.\n",{"id":1250,"difficulty":88,"q":1251,"a":1252},"assign-vs-spread-mixin","What is the difference between mixing into the prototype vs each instance?","Mixing into the **prototype** (`Object.assign(Class.prototype, mixin)`) shares one\ncopy across all instances. Mixing into each **instance** (in the constructor)\ngives every object its own copy — more memory, but allows per-instance\ncustomization.\n\n```js\nObject.assign(User.prototype, mixin)   \u002F\u002F shared (efficient)\n\u002F\u002F vs\nclass User { constructor() { Object.assign(this, mixin) } }  \u002F\u002F per-instance\n```\n\nPrefer prototype mixing for shared stateless behavior. Per-instance mixing is for\nwhen each object needs independently modifiable methods\u002Fstate.\n",{"id":1254,"difficulty":161,"q":1255,"a":1256},"higher-order-component","How does the decorator\u002Fwrapper pattern relate to composition?","A decorator wraps an object\u002Ffunction to add behavior while preserving the\ninterface — composition by **layering**.\n\n```js\nconst withLogging = (fn) => (...args) => {\n  console.log('calling', fn.name, args)\n  return fn(...args)\n}\nconst loggedFetch = withLogging(fetch)\n```\n\nHigher-order functions (and React HOCs) wrap to extend behavior without modifying\nthe original — the same compositional idea as class-factory mixins, applied to\nfunctions\u002Fcomponents.\n",{"id":1258,"difficulty":161,"q":1259,"a":1260},"when-mixin-bad","What are the downsides of mixins?","Mixins can cause **name collisions** (silent overrides), make it unclear where a\nmethod came from (implicit behavior), create hidden coupling between mixin and\nhost, and complicate `this` reasoning.\n\n```js\nObject.assign(C.prototype, a, b, c)  \u002F\u002F which mixin defined `process`? unclear\n```\n\nUse them sparingly and namespace methods to reduce clashes. Often plain\ncomposition\u002Fdelegation (an explicit collaborator object) is clearer than mixing\nmethods into a prototype.\n",{"id":1262,"difficulty":88,"q":1263,"a":1264},"capability-pattern","How do you give an object only the capabilities it needs?","Compose exactly the behaviors required, rather than inheriting a broad base that\nincludes extras.\n\n```js\nconst readable = (store) => ({ read: (k) => store[k] })\nconst writable = (store) => ({ write: (k, v) => { store[k] = v } })\n\nconst readOnly = { ...readable(data) }              \u002F\u002F only read\nconst readWrite = { ...readable(data), ...writable(data) }\n```\n\nThis \"interface segregation\" via composition keeps objects minimal and intention-\nrevealing — you grant precisely the capabilities needed, avoiding the bloat of a\ndo-everything base class.\n",{"id":1266,"difficulty":161,"q":1267,"a":1268},"this-in-mixin","How does this behave inside a mixin method?","A mixin method's `this` is whatever object it's called on (the host instance), so\nit operates on the host's data — that's what makes mixins reusable across types.\n\n```js\nconst describable = {\n  describe() { return `${this.type}: ${this.name}` }\n}\nObject.assign(Product.prototype, describable)\nnew Product().describe()   \u002F\u002F uses the Product's this.type \u002F this.name\n```\n\nThe mixin doesn't care which class it's in — it just uses `this`. Avoid arrow\nfunctions in object-literal mixins (they'd capture the wrong `this`); use regular\nmethod shorthand.\n",{"id":1270,"difficulty":88,"q":1271,"a":1272},"prefer-composition-summary","How do you decide between inheritance, mixins, and composition?","A practical rule of thumb:\n\n- **Inheritance** — a true, stable **is-a** with one parent (`Circle` is a\n  `Shape`).\n- **Mixins** — a **capability** shared by unrelated classes\n  (`Serializable`, `Comparable`).\n- **Composition\u002Fdelegation** — a **has-a** relationship or swappable collaborator\n  (`Car` has an `Engine`).\n\n```js\nclass Circle extends Shape {}                 \u002F\u002F is-a\nObject.assign(Circle.prototype, Serializable) \u002F\u002F capability\nclass Car { #engine = new Engine() }          \u002F\u002F has-a\n```\n\nDefault to composition; reach for inheritance only for genuine is-a hierarchies,\nand mixins for cross-cutting behaviors.\n",{"description":86},"JavaScript mixins and composition interview questions — sharing behavior without inheritance, mixin factories, composition over inheritance, and duck typing.","javascript\u002Fclasses\u002Fmixins-composition","Mixins & Composition","aHIXUIyhSVDUwHvZ-v5yI9JeKd24BUHXfIhRZezvWQU",{"id":1279,"title":1280,"body":1281,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":1285,"navigation":91,"order":38,"path":1286,"questions":1287,"related":224,"seo":1384,"seoDescription":1385,"stem":1386,"subtopic":1387,"topic":55,"topicSlug":57,"updated":228,"__hash__":1388},"qa\u002Fjavascript\u002Fclasses\u002Fstatic-private.md","Static Private",{"type":83,"value":1282,"toc":1283},[],{"title":86,"searchDepth":29,"depth":29,"links":1284},[],{},"\u002Fjavascript\u002Fclasses\u002Fstatic-private",[1288,1292,1296,1300,1304,1308,1312,1316,1320,1324,1328,1332,1336,1340,1344,1348,1352,1356,1360,1364,1368,1372,1376,1380],{"id":1289,"difficulty":88,"q":1290,"a":1291},"static-members","What are static members?","Members (methods or fields) that belong to the **class itself**, not to\ninstances. Accessed as `ClassName.member`.\n\n```js\nclass MathUtil {\n  static PI = 3.14159\n  static square(n) { return n * n }\n}\nMathUtil.PI          \u002F\u002F 3.14159\nMathUtil.square(4)   \u002F\u002F 16\nnew MathUtil().square \u002F\u002F undefined — not on instances\n```\n\nStatics suit utilities and class-level data that don't depend on a particular\ninstance. They're shared (one copy on the class) and inherited by subclasses.\n",{"id":1293,"difficulty":88,"q":1294,"a":1295},"static-methods-use","When do you use a static method?","For operations related to the class but not to a specific instance — most\ncommonly **factory methods** and utilities.\n\n```js\nclass User {\n  constructor(name) { this.name = name }\n  static fromJSON(json) { return new User(JSON.parse(json).name) }\n  static compare(a, b) { return a.name.localeCompare(b.name) }\n}\nconst u = User.fromJSON('{\"name\":\"Ada\"}')\n```\n\nStatic factory methods (`User.fromJSON`, `Array.from`, `Promise.resolve`) are a\ncommon alternative to overloaded constructors. `this` inside a static method is\nthe class.\n",{"id":1297,"difficulty":88,"q":1298,"a":1299},"static-fields","What are static fields?","Class-level properties declared with `static`, shared across all instances and\nthe class — useful for constants, counters, or caches.\n\n```js\nclass Counter {\n  static count = 0           \u002F\u002F shared\n  constructor() { Counter.count++ }\n}\nnew Counter(); new Counter()\nCounter.count   \u002F\u002F 2\n```\n\nReference them via the class name (`Counter.count`), not `this` (in instance\nmethods `this` is the instance). Static fields are a newer feature; older code\nused `Class.prop = value` after the class.\n",{"id":1301,"difficulty":88,"q":1302,"a":1303},"this-in-static","What is this inside a static method?","The **class itself** — so static methods can call sibling statics and respect\nsubclassing.\n\n```js\nclass Base {\n  static create() { return new this() }   \u002F\u002F `this` is the class\n}\nclass Sub extends Base {}\nBase.create()   \u002F\u002F Base instance\nSub.create()    \u002F\u002F Sub instance — `this` is Sub\n```\n\nBecause `this` is the concrete class, a static factory like `create()` builds an\ninstance of whichever subclass it was called on — useful for polymorphic\nfactories.\n",{"id":1305,"difficulty":88,"q":1306,"a":1307},"private-fields","What are private fields and how do you declare them?","Fields prefixed with `#` are **truly private** — accessible only inside the\nclass body, enforced by the language (not a convention).\n\n```js\nclass Account {\n  #balance = 0\n  deposit(n) { this.#balance += n }\n  get balance() { return this.#balance }\n}\nconst a = new Account()\na.#balance         \u002F\u002F SyntaxError outside the class\na.balance          \u002F\u002F via the getter\n```\n\nUnlike the `_underscore` convention, `#private` can't be accessed or even\ndetected from outside. It's real encapsulation built into the syntax.\n",{"id":1309,"difficulty":88,"q":1310,"a":1311},"private-vs-underscore","What is the difference between","`_name` is a **convention** — a hint that a member is internal, but it's still\nfully public and accessible. `#name` is **enforced** privacy — a SyntaxError to\naccess from outside.\n\n```js\nclass C {\n  _soft = 1     \u002F\u002F accessible: c._soft works (just \"please don't\")\n  #hard = 2     \u002F\u002F c.#hard -> SyntaxError\n}\n```\n\nPrefer `#private` for genuine encapsulation. The `_` convention persists in older\ncode and where subclass access is wanted (subclasses can't see `#private`).\n",{"id":1313,"difficulty":88,"q":1314,"a":1315},"private-methods","Can methods be private?","Yes — prefix a method (or getter\u002Fsetter) with `#` to make it callable only from\nwithin the class.\n\n```js\nclass Service {\n  #validate(data) { return !!data }       \u002F\u002F private method\n  get #ready() { return this.#validate(this.data) }  \u002F\u002F private getter\n  submit(data) {\n    this.data = data\n    if (this.#validate(data)) { \u002F* ... *\u002F }\n  }\n}\n```\n\nPrivate methods keep internal helpers off the public API and prevent subclasses\nor callers from depending on them. They live per-class, not on the public\nprototype.\n",{"id":1317,"difficulty":161,"q":1318,"a":1319},"static-private","Can static members be private?","Yes — combine `static` and `#` for private class-level fields and methods,\naccessible only inside the class.\n\n```js\nclass IdGenerator {\n  static #counter = 0\n  static #next() { return ++IdGenerator.#counter }\n  static create() { return { id: IdGenerator.#next() } }\n}\nIdGenerator.#counter   \u002F\u002F SyntaxError\n```\n\nStatic privates are great for internal class state (caches, counters,\nregistries) that shouldn't be touched from outside. Reference them via the class\nname inside the body.\n",{"id":1321,"difficulty":161,"q":1322,"a":1323},"static-block","What is a static initialization block?","A `static { }` block (ES2022) runs once when the class is defined, for complex\nstatic setup that a field initializer can't express — and it can access private\nstatic members.\n\n```js\nclass Config {\n  static settings = {}\n  static {\n    const env = readEnv()             \u002F\u002F run setup logic\n    this.settings = parse(env)\n    this.#secret = deriveSecret(env)  \u002F\u002F can touch private statics\n  }\n  static #secret\n}\n```\n\nIt's the class equivalent of a one-time initializer, useful when static state\nneeds computation, multiple statements, or try\u002Fcatch at definition time.\n",{"id":1325,"difficulty":161,"q":1326,"a":1327},"private-check","How do you check if an object has a private field (brand check)?","Use the `#field in obj` syntax (the \"ergonomic brand check\") — it returns whether\n`obj` has that private field, without throwing.\n\n```js\nclass Stream {\n  #buffer = []\n  static isStream(obj) { return #buffer in obj }\n}\nStream.isStream(new Stream())   \u002F\u002F true\nStream.isStream({})             \u002F\u002F false\n```\n\nThis is the reliable way to detect \"is this a real instance of my class\" — more\nrobust than `instanceof` (which can be spoofed via prototypes). Accessing\n`obj.#buffer` directly on a non-instance would throw, so the `in` form is used.\n",{"id":1329,"difficulty":88,"q":1330,"a":1331},"encapsulation-benefits","Why is encapsulation with private fields valuable?","It hides internal state so callers can't depend on or corrupt it, letting you\nchange the implementation freely and enforce invariants in one place.\n\n```js\nclass Temperature {\n  #celsius = 0\n  set celsius(v) {\n    if (v \u003C -273.15) throw new RangeError('below absolute zero')\n    this.#celsius = v        \u002F\u002F validation can't be bypassed\n  }\n  get celsius() { return this.#celsius }\n}\n```\n\nWith public fields, anyone could set an invalid value directly. Private fields +\naccessors guarantee the validation runs and keep the public surface small and\nstable.\n",{"id":1333,"difficulty":161,"q":1334,"a":1335},"private-inheritance","Are private fields inherited by subclasses?","No — `#private` fields are **not accessible** from subclasses. They belong\nstrictly to the class that declares them.\n\n```js\nclass Base { #secret = 1; getSecret() { return this.#secret } }\nclass Sub extends Base {\n  reveal() { return this.#secret }   \u002F\u002F SyntaxError — not visible\n}\n```\n\nThis is stricter than `protected` in other languages. For state subclasses need,\nuse the `_` convention or expose a protected-style accessor. Private fields are\ntruly class-local.\n",{"id":1337,"difficulty":161,"q":1338,"a":1339},"static-inheritance","Are static members inherited?","Yes — subclasses inherit static methods and fields via the class's own prototype\nchain (`Sub.__proto__ === Base`).\n\n```js\nclass Base { static greet() { return 'hi' } }\nclass Sub extends Base {}\nSub.greet()   \u002F\u002F 'hi' — inherited static\n```\n\nInside an inherited static, `this` is the calling subclass, and `super` reaches\nthe parent's static. Static *fields* are inherited as references — careful, since\na shared static object is shared across the hierarchy.\n",{"id":1341,"difficulty":88,"q":1342,"a":1343},"private-field-must-declare","Do you have to declare private fields before use?","Yes — every private field must be **declared in the class body**. You can't\ncreate one dynamically like a public property.\n\n```js\nclass C {\n  #x = 1            \u002F\u002F must declare\n  m() { this.#y = 2 }   \u002F\u002F SyntaxError — #y not declared\n}\n```\n\nThis is unlike public properties, which can be added anywhere. The requirement\nlets the engine know the full set of private fields at parse time (enabling the\nbrand check and strong encapsulation).\n",{"id":1345,"difficulty":161,"q":1346,"a":1347},"singleton-static","How do you implement a singleton with static members?","Cache the instance in a private static field and expose it via a static getter\nor method, with a guarded\u002Fprivate constructor.\n\n```js\nclass Logger {\n  static #instance\n  static get instance() {\n    return Logger.#instance ??= new Logger()\n  }\n}\nLogger.instance === Logger.instance   \u002F\u002F true\n```\n\nThe private static `#instance` holds the single object; `??=` lazily creates it\nonce. (In JS, a module-level singleton is often simpler, but this is the\nclass-based form.)\n",{"id":1349,"difficulty":88,"q":1350,"a":1351},"static-factory-vs-constructor","Why use static factory methods over constructors?","Static factories can have **descriptive names**, return cached\u002Fsubclass instances,\ndo async work indirectly, and offer multiple \"constructors\" — things a single\nconstructor can't.\n\n```js\nclass Color {\n  constructor(r, g, b) { \u002F* ... *\u002F }\n  static fromHex(hex) { \u002F* parse *\u002F return new Color(\u002F* ... *\u002F) }\n  static fromHSL(h, s, l) { \u002F* convert *\u002F return new Color(\u002F* ... *\u002F) }\n}\n```\n\nNamed factories (`fromHex`, `fromHSL`) read better than overloading one\nconstructor and let you control instance creation (caching, validation). A widely\nused OOP idiom.\n",{"id":1353,"difficulty":88,"q":1354,"a":1355},"private-getter-setter","Can you have private getters and setters?","Yes — `get #name()` \u002F `set #name(v)` define private accessors, usable only inside\nthe class for computed private values.\n\n```js\nclass Box {\n  #w = 0; #h = 0\n  get #area() { return this.#w * this.#h }   \u002F\u002F private computed value\n  report() { return `area: ${this.#area}` }\n}\n```\n\nPrivate accessors are handy for internal derived values you don't want to expose\nor recompute manually. Like all `#` members, they're inaccessible and invisible\noutside the class.\n",{"id":1357,"difficulty":161,"q":1358,"a":1359},"weakmap-privacy","How was privacy done before","With closures (per-instance functions) or a module-scoped **`WeakMap`** keyed by\ninstance — both hide data from outside the class.\n\n```js\nconst _balance = new WeakMap()\nclass Account {\n  constructor() { _balance.set(this, 0) }\n  deposit(n) { _balance.set(this, _balance.get(this) + n) }\n  get balance() { return _balance.get(this) }\n}\n```\n\nThe `WeakMap` lives in module scope, so only the class's methods can read it, and\nentries are garbage-collected with the instance. `#private` fields now do this\nnatively and more cleanly.\n",{"id":1361,"difficulty":88,"q":1362,"a":1363},"static-vs-module","When should you use a static method vs a module function?","Use a **static method** when the function is conceptually tied to the class\n(factories, class-specific helpers, polymorphic via `this`). Use a **plain module\nfunction** for standalone utilities not bound to a class.\n\n```js\n\u002F\u002F tied to the class -> static\nclass Vector { static add(a, b) { \u002F* ... *\u002F } }\n\u002F\u002F generic utility -> module function\nexport function clamp(n, lo, hi) { \u002F* ... *\u002F }\n```\n\nDon't create a class full of only static methods just to namespace functions — a\nmodule is the idiomatic JS namespace. Statics belong with classes that also have\ninstances.\n",{"id":1365,"difficulty":88,"q":1366,"a":1367},"private-method-vs-closure","What is the advantage of a private method over a closure helper?","A `#private` method lives on the class **once** (shared), whereas a closure helper\ndefined per instance (or inside the constructor) is duplicated per object. Private\nmethods give encapsulation **and** memory efficiency.\n\n```js\nclass Service {\n  #parse(x) { \u002F* shared across instances *\u002F }   \u002F\u002F one definition\n}\n\u002F\u002F vs a per-instance closure in the constructor (one function per object)\n```\n\nSo `#private` methods are usually better than closure-based privacy for classes:\nsame hiding, no per-instance function cost.\n",{"id":1369,"difficulty":88,"q":1370,"a":1371},"enum-pattern","How do you create enum-like constants with static members?","Use static fields (often on a frozen class) to model a fixed set of named\nconstants.\n\n```js\nclass Direction {\n  static North = new Direction('N')\n  static South = new Direction('S')\n  constructor(code) { this.code = code }\n}\nObject.freeze(Direction)\nDirection.North.code   \u002F\u002F 'N'\n```\n\nJavaScript has no native `enum`, so frozen static instances (or a frozen plain\nobject `Object.freeze({ North: 'N', ... })`) are the common patterns for\nenumerations.\n",{"id":1373,"difficulty":161,"q":1374,"a":1375},"static-this-pitfall","What is a common pitfall referencing static fields?","Inside an **instance** method, `this` is the instance, so `this.staticField` is\n`undefined` — you must use the class name (or `this.constructor`).\n\n```js\nclass C {\n  static MAX = 10\n  check(n) {\n    return n \u003C this.MAX            \u002F\u002F undefined — MAX is static\n    \u002F\u002F return n \u003C C.MAX            \u002F\u002F\n    \u002F\u002F return n \u003C this.constructor.MAX  \u002F\u002F subclass-aware\n  }\n}\n```\n\nUse `ClassName.field` for a fixed reference, or `this.constructor.field` if you\nwant subclasses to be able to override the static value.\n",{"id":1377,"difficulty":161,"q":1378,"a":1379},"private-in-operator-guard","Why does accessing a private field on the wrong object throw?","Private fields are \"branded\" to their class. Reading `obj.#field` on an object\nthat isn't an instance throws a `TypeError`, which protects encapsulation but\nmeans you should guard with `#field in obj` first.\n\n```js\nclass A { #x = 1; static read(o) { return #x in o ? o.#x : null } }\nA.read(new A())   \u002F\u002F 1\nA.read({})        \u002F\u002F null (guarded; direct o.#x would throw)\n```\n\nThe throw-on-mismatch behavior is what makes `#field in obj` the safe brand\ncheck, and prevents one class's private accessor from working on foreign objects.\n",{"id":1381,"difficulty":88,"q":1382,"a":1383},"freeze-class","How do you make a class's static configuration immutable?","Freeze the class (and\u002For its static objects) so static fields can't be reassigned\nafter definition.\n\n```js\nclass Config {\n  static API = '\u002Fv1'\n  static TIMEOUT = 5000\n}\nObject.freeze(Config)\nConfig.API = '\u002Fv2'   \u002F\u002F ignored (throws in strict mode)\n```\n\n`Object.freeze(Config)` locks top-level static props; nested static objects need\ntheir own freeze (it's shallow). A `static {}` block plus `Object.freeze` is a\nclean way to set up immutable class-level config.\n",{"description":86},"JavaScript static and private class member interview questions — static methods and fields, private fields and methods, static blocks, and encapsulation patterns.","javascript\u002Fclasses\u002Fstatic-private","Static & Private Members","J6BpWyoml9KkWfwfDsQHBLHqJm6SUDbQqoQYjj8Gipc",{"id":1390,"title":1391,"body":1392,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":1396,"navigation":91,"order":11,"path":1397,"questions":1398,"related":224,"seo":1535,"seoDescription":1536,"stem":1537,"subtopic":1391,"topic":28,"topicSlug":30,"updated":789,"__hash__":1538},"qa\u002Fjavascript\u002Ffunctions\u002Fclosures.md","Closures",{"type":83,"value":1393,"toc":1394},[],{"title":86,"searchDepth":29,"depth":29,"links":1395},[],{},"\u002Fjavascript\u002Ffunctions\u002Fclosures",[1399,1403,1407,1411,1415,1419,1423,1427,1431,1435,1439,1443,1447,1451,1455,1459,1463,1467,1471,1475,1479,1483,1487,1491,1495,1499,1503,1507,1511,1515,1519,1523,1527,1531],{"id":1400,"difficulty":88,"q":1401,"a":1402},"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":1404,"difficulty":88,"q":1405,"a":1406},"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":1408,"difficulty":161,"q":1409,"a":1410},"closure-memory","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":1412,"difficulty":161,"q":1413,"a":1414},"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":1416,"difficulty":88,"q":1417,"a":1418},"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":1420,"difficulty":88,"q":1421,"a":1422},"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":1424,"difficulty":96,"q":1425,"a":1426},"iife","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":1428,"difficulty":88,"q":1429,"a":1430},"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":1432,"difficulty":88,"q":1433,"a":1434},"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":1436,"difficulty":161,"q":1437,"a":1438},"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":1440,"difficulty":161,"q":1441,"a":1442},"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":1444,"difficulty":88,"q":1445,"a":1446},"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":1448,"difficulty":161,"q":1449,"a":1450},"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":1452,"difficulty":88,"q":1453,"a":1454},"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":1456,"difficulty":88,"q":1457,"a":1458},"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":1460,"difficulty":161,"q":1461,"a":1462},"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":1464,"difficulty":161,"q":1465,"a":1466},"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":1468,"difficulty":88,"q":1469,"a":1470},"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":1472,"difficulty":88,"q":1473,"a":1474},"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":1476,"difficulty":96,"q":1477,"a":1478},"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":1480,"difficulty":161,"q":1481,"a":1482},"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":1484,"difficulty":88,"q":1485,"a":1486},"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":1488,"difficulty":88,"q":1489,"a":1490},"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":1492,"difficulty":161,"q":1493,"a":1494},"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":1496,"difficulty":161,"q":1497,"a":1498},"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":1500,"difficulty":161,"q":1501,"a":1502},"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":1504,"difficulty":88,"q":1505,"a":1506},"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":1508,"difficulty":96,"q":1509,"a":1510},"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":1512,"difficulty":161,"q":1513,"a":1514},"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":1516,"difficulty":88,"q":1517,"a":1518},"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":1520,"difficulty":96,"q":1521,"a":1522},"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":1524,"difficulty":88,"q":1525,"a":1526},"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":1528,"difficulty":88,"q":1529,"a":1530},"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":1532,"difficulty":88,"q":1533,"a":1534},"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",{"description":86},"JavaScript closure interview questions and answers — what closures are, how they capture variables, practical uses and common pitfalls.","javascript\u002Ffunctions\u002Fclosures","fIkqXiaH8g__RSSbGGQQ3i6Y8gV63cRtxHtJRDtN9gg",{"id":1540,"title":1541,"body":1542,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":1546,"navigation":91,"order":47,"path":1547,"questions":1548,"related":224,"seo":1669,"seoDescription":1670,"stem":1671,"subtopic":1672,"topic":28,"topicSlug":30,"updated":228,"__hash__":1673},"qa\u002Fjavascript\u002Ffunctions\u002Ffunction-types-parameters.md","Function Types Parameters",{"type":83,"value":1543,"toc":1544},[],{"title":86,"searchDepth":29,"depth":29,"links":1545},[],{},"\u002Fjavascript\u002Ffunctions\u002Ffunction-types-parameters",[1549,1553,1557,1561,1565,1569,1573,1577,1581,1585,1589,1593,1597,1601,1605,1609,1613,1617,1621,1625,1629,1633,1637,1641,1645,1649,1653,1657,1661,1665],{"id":1550,"difficulty":96,"q":1551,"a":1552},"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":1554,"difficulty":96,"q":1555,"a":1556},"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":1558,"difficulty":88,"q":1559,"a":1560},"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":1562,"difficulty":88,"q":1563,"a":1564},"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":1566,"difficulty":96,"q":1567,"a":1568},"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":1570,"difficulty":96,"q":1571,"a":1572},"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":1574,"difficulty":161,"q":1575,"a":1576},"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":1578,"difficulty":88,"q":1579,"a":1580},"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":1582,"difficulty":88,"q":1583,"a":1584},"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":1586,"difficulty":88,"q":1587,"a":1588},"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":1590,"difficulty":88,"q":1591,"a":1592},"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":1594,"difficulty":96,"q":1595,"a":1596},"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":1598,"difficulty":88,"q":1599,"a":1600},"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":1602,"difficulty":96,"q":1603,"a":1604},"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":1606,"difficulty":88,"q":1607,"a":1608},"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":1610,"difficulty":88,"q":1611,"a":1612},"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":1614,"difficulty":161,"q":1615,"a":1616},"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":1618,"difficulty":96,"q":1619,"a":1620},"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":1622,"difficulty":88,"q":1623,"a":1624},"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":1626,"difficulty":88,"q":1627,"a":1628},"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":1630,"difficulty":96,"q":1631,"a":1632},"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":1634,"difficulty":161,"q":1635,"a":1636},"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":1638,"difficulty":88,"q":1639,"a":1640},"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":1642,"difficulty":88,"q":1643,"a":1644},"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":1646,"difficulty":88,"q":1647,"a":1648},"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":1650,"difficulty":161,"q":1651,"a":1652},"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":1654,"difficulty":88,"q":1655,"a":1656},"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":1658,"difficulty":88,"q":1659,"a":1660},"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":1662,"difficulty":161,"q":1663,"a":1664},"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":1666,"difficulty":161,"q":1667,"a":1668},"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":86},"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":1675,"title":1676,"body":1677,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":1681,"navigation":91,"order":56,"path":1682,"questions":1683,"related":224,"seo":1803,"seoDescription":1804,"stem":1805,"subtopic":1806,"topic":28,"topicSlug":30,"updated":228,"__hash__":1807},"qa\u002Fjavascript\u002Ffunctions\u002Fgenerators-iterators.md","Generators Iterators",{"type":83,"value":1678,"toc":1679},[],{"title":86,"searchDepth":29,"depth":29,"links":1680},[],{},"\u002Fjavascript\u002Ffunctions\u002Fgenerators-iterators",[1684,1688,1692,1696,1700,1704,1708,1712,1716,1720,1724,1728,1732,1736,1740,1744,1748,1752,1756,1760,1764,1767,1771,1775,1779,1783,1787,1791,1795,1799],{"id":1685,"difficulty":88,"q":1686,"a":1687},"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":1689,"difficulty":88,"q":1690,"a":1691},"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":1693,"difficulty":96,"q":1694,"a":1695},"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":1697,"difficulty":96,"q":1698,"a":1699},"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":1701,"difficulty":96,"q":1702,"a":1703},"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":1705,"difficulty":88,"q":1706,"a":1707},"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":1709,"difficulty":88,"q":1710,"a":1711},"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":1713,"difficulty":88,"q":1714,"a":1715},"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":1717,"difficulty":88,"q":1718,"a":1719},"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":1721,"difficulty":88,"q":1722,"a":1723},"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":1725,"difficulty":88,"q":1726,"a":1727},"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":1729,"difficulty":161,"q":1730,"a":1731},"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":1733,"difficulty":161,"q":1734,"a":1735},"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":1737,"difficulty":161,"q":1738,"a":1739},"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":1741,"difficulty":88,"q":1742,"a":1743},"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":1745,"difficulty":161,"q":1746,"a":1747},"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":1749,"difficulty":88,"q":1750,"a":1751},"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":1753,"difficulty":88,"q":1754,"a":1755},"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":1757,"difficulty":88,"q":1758,"a":1759},"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":1761,"difficulty":161,"q":1762,"a":1763},"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":885,"difficulty":161,"q":1765,"a":1766},"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":1768,"difficulty":161,"q":1769,"a":1770},"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":1772,"difficulty":88,"q":1773,"a":1774},"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":1776,"difficulty":161,"q":1777,"a":1778},"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":1780,"difficulty":161,"q":1781,"a":1782},"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":1784,"difficulty":88,"q":1785,"a":1786},"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":1788,"difficulty":88,"q":1789,"a":1790},"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":1792,"difficulty":88,"q":1793,"a":1794},"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":1796,"difficulty":161,"q":1797,"a":1798},"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":1800,"difficulty":88,"q":1801,"a":1802},"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":86},"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",{"id":1809,"title":1810,"body":1811,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":1815,"navigation":91,"order":38,"path":1816,"questions":1817,"related":224,"seo":1941,"seoDescription":1942,"stem":1943,"subtopic":1944,"topic":28,"topicSlug":30,"updated":228,"__hash__":1945},"qa\u002Fjavascript\u002Ffunctions\u002Fhigher-order-functions.md","Higher Order Functions",{"type":83,"value":1812,"toc":1813},[],{"title":86,"searchDepth":29,"depth":29,"links":1814},[],{},"\u002Fjavascript\u002Ffunctions\u002Fhigher-order-functions",[1818,1822,1826,1830,1834,1838,1842,1846,1850,1853,1857,1861,1865,1869,1873,1877,1881,1885,1889,1893,1897,1901,1905,1909,1913,1917,1921,1925,1929,1933,1937],{"id":1819,"difficulty":96,"q":1820,"a":1821},"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":1823,"difficulty":96,"q":1824,"a":1825},"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":1827,"difficulty":96,"q":1828,"a":1829},"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":1831,"difficulty":96,"q":1832,"a":1833},"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":1835,"difficulty":88,"q":1836,"a":1837},"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":1839,"difficulty":88,"q":1840,"a":1841},"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":1843,"difficulty":88,"q":1844,"a":1845},"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":1847,"difficulty":88,"q":1848,"a":1849},"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":1452,"difficulty":88,"q":1851,"a":1852},"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":1854,"difficulty":161,"q":1855,"a":1856},"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":1858,"difficulty":88,"q":1859,"a":1860},"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":1862,"difficulty":88,"q":1863,"a":1864},"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":1866,"difficulty":88,"q":1867,"a":1868},"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":1870,"difficulty":88,"q":1871,"a":1872},"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":1874,"difficulty":88,"q":1875,"a":1876},"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":1878,"difficulty":88,"q":1879,"a":1880},"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":1882,"difficulty":161,"q":1883,"a":1884},"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":1886,"difficulty":161,"q":1887,"a":1888},"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":1890,"difficulty":88,"q":1891,"a":1892},"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":1894,"difficulty":88,"q":1895,"a":1896},"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":1898,"difficulty":96,"q":1899,"a":1900},"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":1902,"difficulty":161,"q":1903,"a":1904},"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":1906,"difficulty":88,"q":1907,"a":1908},"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":1910,"difficulty":161,"q":1911,"a":1912},"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":1914,"difficulty":88,"q":1915,"a":1916},"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":1918,"difficulty":88,"q":1919,"a":1920},"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":1922,"difficulty":161,"q":1923,"a":1924},"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":1926,"difficulty":161,"q":1927,"a":1928},"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":1930,"difficulty":161,"q":1931,"a":1932},"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":1934,"difficulty":88,"q":1935,"a":1936},"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":1938,"difficulty":161,"q":1939,"a":1940},"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":86},"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","gajpsA9HuJ91gZ5frBbNlC6sHDnB7KjdH7Q19PqI4FY",{"id":1947,"title":1948,"body":1949,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":1953,"navigation":91,"order":29,"path":1954,"questions":1955,"related":224,"seo":2087,"seoDescription":2088,"stem":2089,"subtopic":2090,"topic":28,"topicSlug":30,"updated":789,"__hash__":2091},"qa\u002Fjavascript\u002Ffunctions\u002Fthis-keyword.md","This Keyword",{"type":83,"value":1950,"toc":1951},[],{"title":86,"searchDepth":29,"depth":29,"links":1952},[],{},"\u002Fjavascript\u002Ffunctions\u002Fthis-keyword",[1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004,2008,2012,2016,2020,2024,2028,2032,2036,2040,2043,2047,2051,2055,2059,2063,2067,2071,2075,2079,2083],{"id":1957,"difficulty":88,"q":1958,"a":1959},"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":1961,"difficulty":88,"q":1962,"a":1963},"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":1965,"difficulty":88,"q":1966,"a":1967},"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":1969,"difficulty":161,"q":1970,"a":1971},"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":1973,"difficulty":88,"q":1974,"a":1975},"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":1977,"difficulty":88,"q":1978,"a":1979},"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":1981,"difficulty":161,"q":1982,"a":1983},"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":1985,"difficulty":88,"q":1986,"a":1987},"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":1989,"difficulty":88,"q":1990,"a":1991},"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":1993,"difficulty":88,"q":1994,"a":1995},"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":1997,"difficulty":88,"q":1998,"a":1999},"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":2001,"difficulty":161,"q":2002,"a":2003},"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":2005,"difficulty":88,"q":2006,"a":2007},"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":2009,"difficulty":88,"q":2010,"a":2011},"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":2013,"difficulty":88,"q":2014,"a":2015},"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":2017,"difficulty":88,"q":2018,"a":2019},"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":2021,"difficulty":161,"q":2022,"a":2023},"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":2025,"difficulty":96,"q":2026,"a":2027},"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":2029,"difficulty":88,"q":2030,"a":2031},"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":2033,"difficulty":88,"q":2034,"a":2035},"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":2037,"difficulty":88,"q":2038,"a":2039},"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":2041,"difficulty":88,"q":1302,"a":2042},"this-static","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":2044,"difficulty":96,"q":2045,"a":2046},"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":2048,"difficulty":88,"q":2049,"a":2050},"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":2052,"difficulty":88,"q":2053,"a":2054},"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":2056,"difficulty":161,"q":2057,"a":2058},"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":2060,"difficulty":88,"q":2061,"a":2062},"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":2064,"difficulty":88,"q":2065,"a":2066},"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":2068,"difficulty":96,"q":2069,"a":2070},"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":2072,"difficulty":161,"q":2073,"a":2074},"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":2076,"difficulty":161,"q":2077,"a":2078},"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":2080,"difficulty":88,"q":2081,"a":2082},"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":2084,"difficulty":88,"q":2085,"a":2086},"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":86},"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":2093,"title":2094,"body":2095,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":2099,"navigation":91,"order":29,"path":2100,"questions":2101,"related":224,"seo":2233,"seoDescription":2234,"stem":2235,"subtopic":2236,"topic":20,"topicSlug":21,"updated":789,"__hash__":2237},"qa\u002Fjavascript\u002Ffundamentals\u002Fdata-types-coercion.md","Data Types Coercion",{"type":83,"value":2096,"toc":2097},[],{"title":86,"searchDepth":29,"depth":29,"links":2098},[],{},"\u002Fjavascript\u002Ffundamentals\u002Fdata-types-coercion",[2102,2106,2110,2114,2118,2122,2125,2129,2133,2137,2141,2145,2149,2153,2157,2161,2165,2169,2173,2177,2181,2185,2189,2193,2197,2201,2205,2209,2213,2217,2221,2225,2229],{"id":2103,"difficulty":96,"q":2104,"a":2105},"primitives","What are the primitive types in JavaScript?","There are **seven primitive types**: `string`, `number`, `boolean`, `null`,\n`undefined`, `symbol`, and `bigint`. Everything that isn't a primitive is an\n**object** — and that includes arrays, functions, dates, and `null`'s\nmisleading `typeof`.\n\n```js\ntypeof 'hi'        \u002F\u002F 'string'\ntypeof 42          \u002F\u002F 'number'\ntypeof true        \u002F\u002F 'boolean'\ntypeof undefined   \u002F\u002F 'undefined'\ntypeof Symbol()    \u002F\u002F 'symbol'\ntypeof 10n         \u002F\u002F 'bigint'\ntypeof null        \u002F\u002F 'object'  \u003C- historical bug, null IS a primitive\n```\n\nTwo defining traits: primitives are **immutable** (you can't change the value\nitself, only rebind the variable) and they're **compared by value**, whereas\nobjects are mutable and **compared by reference**. When you call a method like\n`'hi'.toUpperCase()`, JS temporarily wraps the primitive in an object\n(autoboxing) and discards it afterward.\n",{"id":2107,"difficulty":96,"q":2108,"a":2109},"eqeq-vs-eqeqeq","What is the difference between == and ===?","`===` is **strict equality**: it compares **value *and* type** with no\nconversion — if the types differ, it's immediately `false`. `==` is **loose\nequality**: it **coerces** the operands toward a common type first, which\nproduces a list of surprising results.\n\n```js\n0 === ''      \u002F\u002F false (number vs string)\n0 == ''       \u002F\u002F true  (both coerce to 0)\n0 == '0'      \u002F\u002F true\n'' == '0'     \u002F\u002F false  \u003C- not even transitive!\nnull == undefined \u002F\u002F true (special-cased)\nNaN == NaN    \u002F\u002F false\n[] == ![]     \u002F\u002F true  (classic \"wtf\" — [] coerces to '', ![] is false -> 0)\n```\n\n**Prefer `===` virtually always** — it's predictable and the coercion rules\nbehind `==` are a frequent bug source. The one common idiomatic exception is\n`x == null`, which conveniently matches *both* `null` and `undefined`.\n",{"id":2111,"difficulty":88,"q":2112,"a":2113},"coercion","What is type coercion?","Coercion is JavaScript **automatically converting** a value from one type to\nanother. It comes in two flavors: **implicit** (the engine does it for you\nduring an operation, e.g. `'5' * 2`) and **explicit** (you ask for it,\n`Number('5')`, `String(5)`, `Boolean(0)`).\n\nThe operator that trips everyone up is `+`: if **either** side is a string, it\ndoes **string concatenation**; otherwise it does numeric addition. The other\narithmetic operators (`-`, `*`, `\u002F`) have no string meaning, so they coerce to\nnumbers.\n\n```js\n1 + '2'    \u002F\u002F '12'   (+ with a string -> concatenation)\n1 - '2'    \u002F\u002F -1     (- forces numeric -> 1 - 2)\n'5' * '2'  \u002F\u002F 10     (* forces numeric)\ntrue + 1   \u002F\u002F 2      (true -> 1)\n[] + {}    \u002F\u002F '[object Object]'  (both -> strings)\n```\n\nIn an interview, narrate the rule (\"`+` prefers strings, the rest prefer\nnumbers\") rather than memorizing every edge case.\n",{"id":2115,"difficulty":96,"q":2116,"a":2117},"truthy-falsy","Which values are falsy in JavaScript?","There are exactly **eight falsy values** — memorize the list, because\n*everything else is truthy*:\n\n```js\nfalse\n0\n-0\n0n        \u002F\u002F BigInt zero\n''        \u002F\u002F empty string\nnull\nundefined\nNaN\n```\n\nThe famous gotchas are the things people *expect* to be falsy but aren't:\n`'0'`, `'false'`, `[]` (empty array), and `{}` (empty object) are **all\ntruthy**.\n\n```js\nif ([]) console.log('runs!')   \u002F\u002F empty array is truthy\nif ('0') console.log('runs!')  \u002F\u002F non-empty string is truthy\nBoolean([]) \u002F\u002F true\n```\n\nThis matters for `if` conditions, `||`\u002F`&&`, and the nullish coalescing\noperator `??` (which, unlike `||`, only falls back on `null`\u002F`undefined`, not\non `0` or `''`).\n",{"id":2119,"difficulty":88,"q":2120,"a":2121},"null-undefined","What is the difference between null and undefined?","Both represent \"no value,\" but they signal different *intents*:\n\n- `undefined` is the language's default \"absence\" — a declared-but-unassigned\n  variable, a missing object property, a missing function argument, or the\n  return of a function with no `return`. The **engine** produces it.\n- `null` is an **intentional, explicit** \"no value here\" that **you** assign to\n  say \"this is deliberately empty.\"\n\n```js\nlet a               \u002F\u002F undefined (never assigned)\nconst obj = {}\nobj.missing         \u002F\u002F undefined (no such property)\nconst b = null      \u002F\u002F null (you chose emptiness)\n\ntypeof undefined    \u002F\u002F 'undefined'\ntypeof null         \u002F\u002F 'object'  \u003C- long-standing bug, never fixed for compat\nnull == undefined   \u002F\u002F true  (loose — they're \"equal absences\")\nnull === undefined  \u002F\u002F false (different types)\n```\n",{"id":2123,"difficulty":88,"q":214,"a":2124},"typeof-array","Use **`Array.isArray(value)`**. You can't use `typeof`, because arrays are\nobjects, so `typeof []` returns `'object'` — indistinguishable from a plain\nobject or `null`.\n\n```js\ntypeof []              \u002F\u002F 'object'  \u003C- useless for arrays\nArray.isArray([])      \u002F\u002F true\nArray.isArray({})      \u002F\u002F false\nArray.isArray('abc')   \u002F\u002F false\n```\n\n`Array.isArray` is also more robust than the older\n`value instanceof Array` trick, because `instanceof` **breaks across\nrealms** (e.g. an array coming from an `\u003Ciframe>` has a different `Array`\nconstructor, so `instanceof` returns `false`). `Array.isArray` works\nregardless of realm.\n",{"id":2126,"difficulty":161,"q":2127,"a":2128},"nan","Why is NaN === NaN false, and how do you test for NaN?","`NaN` (\"Not-a-Number\") is, by the IEEE-754 spec and ECMAScript, the **only\nvalue not equal to itself** — there are many distinct computations that produce\n\"not a number,\" so the standard defines all comparisons with `NaN` (including\n`NaN === NaN`) as `false`. You therefore can't detect it with `===`.\n\n```js\nNaN === NaN          \u002F\u002F false\n0 \u002F 0                \u002F\u002F NaN\nNumber('abc')        \u002F\u002F NaN\n\nNumber.isNaN(NaN)    \u002F\u002F true  reliable\nNumber.isNaN('abc')  \u002F\u002F false (no coercion — 'abc' simply isn't NaN)\n\nisNaN('abc')         \u002F\u002F true  misleading: it coerces 'abc' -> NaN first\n```\n\nUse **`Number.isNaN(value)`** (ES2015), which checks \"is this *literally* the\nNaN value.\" Avoid the **global `isNaN`**, which coerces its argument to a number\nfirst and so reports `true` for plenty of non-NaN inputs. (Another trick that\nworks: `value !== value` is `true` only for `NaN`.)\n",{"id":2130,"difficulty":88,"q":2131,"a":2132},"object-is","What is Object.is and how does it differ from ===?","`Object.is(a, b)` is \"same-value\" equality. It behaves like `===` **except** for\ntwo edge cases: it treats `NaN` as equal to itself, and it distinguishes `+0`\nfrom `-0`.\n\n```js\nObject.is(NaN, NaN)  \u002F\u002F true   (=== gives false)\nObject.is(0, -0)     \u002F\u002F false  (=== gives true)\nObject.is(1, 1)      \u002F\u002F true\n```\n\nIt's the same algorithm React uses to decide whether state\u002Fprops changed. Use\n`===` for normal comparisons; reach for `Object.is` when those two `NaN`\u002F`-0`\nedge cases actually matter.\n",{"id":2134,"difficulty":161,"q":2135,"a":2136},"plus-minus-zero","What is the difference between +0 and -0?","JavaScript has a signed zero: `+0` and `-0` are distinct bit patterns. They're\n**equal** under `==` and `===`, but distinguishable with `Object.is` or by\ndividing (which exposes the sign via `Infinity`).\n\n```js\n+0 === -0           \u002F\u002F true\nObject.is(+0, -0)   \u002F\u002F false\n1 \u002F +0              \u002F\u002F Infinity\n1 \u002F -0              \u002F\u002F -Infinity\n```\n\n`-0` arises from operations like `-1 * 0` or `Math.round(-0.1)`. It rarely matters,\nbut can surprise you in sign-sensitive math or when used as a Map key.\n",{"id":2138,"difficulty":96,"q":2139,"a":2140},"typeof-function","What does typeof return for a function?","`typeof` returns `'function'` for any callable — function declarations,\nexpressions, arrows, classes, and methods. This is a special case: functions are\ntechnically objects, but `typeof` singles them out.\n\n```js\ntypeof function () {}  \u002F\u002F 'function'\ntypeof (() => {})      \u002F\u002F 'function'\ntypeof class {}        \u002F\u002F 'function' (classes are functions under the hood)\ntypeof Math.max        \u002F\u002F 'function'\ntypeof []              \u002F\u002F 'object' (arrays are NOT singled out)\n```\n\nIt's the reliable way to check \"is this callable?\" before invoking\n(`typeof cb === 'function'`).\n",{"id":2142,"difficulty":88,"q":2143,"a":2144},"typeof-results","What are all the possible results of typeof?","`typeof` returns one of eight strings:\n\n```js\ntypeof 'a'        \u002F\u002F 'string'\ntypeof 1          \u002F\u002F 'number'\ntypeof true       \u002F\u002F 'boolean'\ntypeof undefined  \u002F\u002F 'undefined'\ntypeof 10n        \u002F\u002F 'bigint'\ntypeof Symbol()   \u002F\u002F 'symbol'\ntypeof function(){}\u002F\u002F 'function'\ntypeof {}         \u002F\u002F 'object'  (also arrays, null, dates, etc.)\n```\n\nThe famous quirk is **`typeof null === 'object'`** — a bug kept for backward\ncompatibility. Anything not in the first seven categories (including arrays and\n`null`) reports `'object'`, which is why you need `Array.isArray` and\n`=== null`.\n",{"id":2146,"difficulty":161,"q":2147,"a":2148},"boxing","What is autoboxing of primitives?","Primitives have no methods, yet `'hi'.toUpperCase()` works because JavaScript\ntemporarily **wraps** the primitive in its object form (`String`, `Number`,\n`Boolean`), calls the method, then discards the wrapper.\n\n```js\n'hi'.length        \u002F\u002F 2 — boxed to a String object momentarily\n(5).toFixed(2)     \u002F\u002F '5.00' — boxed to Number\n\n\u002F\u002F explicit wrapper objects are an anti-pattern:\nconst n = new Number(5)\ntypeof n           \u002F\u002F 'object', not 'number'\nn === 5            \u002F\u002F false\n```\n\nNever use `new Number`\u002F`new String` — the resulting objects break `===` and are\nalways truthy (`new Boolean(false)` is truthy!). Let autoboxing happen\nimplicitly.\n",{"id":2150,"difficulty":88,"q":2151,"a":2152},"parseint-vs-number","What is the difference between parseInt and Number?","- **`Number(x)`** converts the **entire** string to a number; any invalid\n  character makes the whole thing `NaN`. Handles decimals.\n- **`parseInt(x, radix)`** reads an **integer prefix**, stopping at the first\n  non-numeric character, and ignores the rest. Always pass the radix.\n\n```js\nNumber('42px')      \u002F\u002F NaN\nparseInt('42px', 10)\u002F\u002F 42 (parses the leading 42)\nNumber('3.14')      \u002F\u002F 3.14\nparseInt('3.14', 10)\u002F\u002F 3 (integer only)\nparseInt('0x1F', 16)\u002F\u002F 31\nNumber('')          \u002F\u002F 0  (parseInt('') is NaN)\n```\n\nUse `Number`\u002F`parseFloat` for exact full-string conversion; `parseInt` for\nextracting a leading integer (e.g. `'20px'` -> `20`).\n",{"id":2154,"difficulty":161,"q":2155,"a":2156},"eqeq-steps","What steps does == take to coerce operands?","The abstract equality (`==`) algorithm, simplified:\n\n1. Same type -> compare like `===`.\n2. `null == undefined` -> `true` (and they equal nothing else).\n3. number vs string -> convert the **string to a number**.\n4. boolean vs anything -> convert the **boolean to a number** (`true`->1, `false`->0).\n5. object vs primitive -> convert the **object to a primitive** (`valueOf`\u002F\n   `toString`), then retry.\n\n```js\n'5' == 5      \u002F\u002F string->number: 5 == 5 -> true\ntrue == 1     \u002F\u002F boolean->number: 1 == 1 -> true\n[] == 0       \u002F\u002F [] -> '' -> 0; 0 == 0 -> true\n[] == ![]     \u002F\u002F ![] is false->0; [] -> 0; true\n```\n\nKnowing these steps explains every \"wat\" example — and is the best argument for\nalways using `===`.\n",{"id":2158,"difficulty":161,"q":2159,"a":2160},"toprimitive","How does an object convert to a primitive (Symbol.toPrimitive)?","When an object is used where a primitive is expected, JS calls its\n`Symbol.toPrimitive` method (if present) with a **hint** (`'number'`, `'string'`,\nor `'default'`); otherwise it falls back to `valueOf` then `toString`.\n\n```js\nconst money = {\n  amount: 100,\n  [Symbol.toPrimitive](hint) {\n    return hint === 'string' ? `$${this.amount}` : this.amount\n  },\n}\n`${money}`   \u002F\u002F '$100'  (hint 'string')\nmoney + 1    \u002F\u002F 101     (hint 'default' -> number)\nmoney * 2    \u002F\u002F 200     (hint 'number')\n```\n\nThis lets you control how objects behave in concatenation, arithmetic, and\ntemplate literals.\n",{"id":2162,"difficulty":88,"q":2163,"a":2164},"valueof-tostring","What roles do valueOf and toString play in coercion?","Without `Symbol.toPrimitive`, object-to-primitive conversion uses these two: for a\n**number** hint it tries `valueOf` first; for a **string** hint it tries\n`toString` first. Whichever returns a primitive wins.\n\n```js\nconst obj = {\n  valueOf() { return 42 },\n  toString() { return 'hello' },\n}\nobj + 1       \u002F\u002F 43      (default\u002Fnumber hint -> valueOf)\n`${obj}`      \u002F\u002F 'hello' (string hint -> toString)\nString(obj)   \u002F\u002F 'hello'\nNumber(obj)   \u002F\u002F 42\n```\n\nOverride `toString` (and sometimes `valueOf`) to make your objects coerce\nsensibly in logs and expressions.\n",{"id":2166,"difficulty":96,"q":2167,"a":2168},"template-coercion","How does coercion work in template literals?","Template literals coerce every interpolated value to a **string** (using\n`String()` \u002F the object's `toString`). This is convenient but can produce\n`[object Object]` or `undefined`\u002F`null` text.\n\n```js\n`count: ${5}`        \u002F\u002F 'count: 5'\n`arr: ${[1, 2, 3]}`  \u002F\u002F 'arr: 1,2,3' (array toString joins with commas)\n`obj: ${ {a: 1} }`   \u002F\u002F 'obj: [object Object]'\n`val: ${null}`       \u002F\u002F 'val: null'\n```\n\nFor objects, interpolate a specific field or `JSON.stringify(obj)` rather than\nrelying on the default `[object Object]`.\n",{"id":2170,"difficulty":161,"q":2171,"a":2172},"json-stringify","What are the edge cases of JSON.stringify?","`JSON.stringify` silently **drops or transforms** several types: `undefined`,\nfunctions, and symbols are **omitted** in objects (or become `null` in arrays);\n`NaN`\u002F`Infinity` become `null`; `BigInt` **throws**; and `Date` becomes an ISO\nstring.\n\n```js\nJSON.stringify({ a: undefined, b: () => {}, c: NaN })\n\u002F\u002F '{\"c\":null}'  — a and b dropped, NaN -> null\nJSON.stringify([undefined, function(){}, 1])\n\u002F\u002F '[null,null,1]'\nJSON.stringify(10n) \u002F\u002F TypeError: BigInt not serializable\n```\n\nIt also calls a value's `toJSON()` if present, and ignores non-enumerable\nproperties. Know these when serializing for APIs or storage.\n",{"id":2174,"difficulty":88,"q":2175,"a":2176},"float-precision","Why does 0.1 + 0.2 not equal 0.3 in JavaScript?","All JS numbers are 64-bit IEEE-754 **doubles**. Decimal fractions like `0.1` can't\nbe represented exactly in binary, so they're stored as the nearest approximation\nand rounding errors accumulate.\n\n```js\n0.1 + 0.2            \u002F\u002F 0.30000000000000004\n0.1 + 0.2 === 0.3    \u002F\u002F false\n\n\u002F\u002F compare with a tolerance instead:\nMath.abs(0.1 + 0.2 - 0.3) \u003C Number.EPSILON \u002F\u002F true\n```\n\nFor money, work in integer **cents** or use a decimal library. Never compare\nfloats with `===`; use an epsilon tolerance.\n",{"id":2178,"difficulty":88,"q":2179,"a":2180},"bigint","What is BigInt and how does it differ from Number?","`BigInt` represents integers of **arbitrary precision**, beyond the safe integer\nlimit of `Number` (`2^53 - 1`). Create one with an `n` suffix or `BigInt()`.\n\n```js\nNumber.MAX_SAFE_INTEGER          \u002F\u002F 9007199254740991\n9007199254740991 + 2             \u002F\u002F 9007199254740992 (wrong! lost precision)\n9007199254740991n + 2n           \u002F\u002F 9007199254740993n (exact)\n```\n\nCaveats: you **can't mix** `BigInt` and `Number` in arithmetic (`1n + 1` throws),\n`typeof 1n === 'bigint'`, and it's integer-only (no decimals). Use it for large\nIDs, timestamps in nanoseconds, and exact big-integer math.\n",{"id":2182,"difficulty":88,"q":2183,"a":2184},"nullish-coalescing","What is the nullish coalescing operator (??)?","`a ?? b` returns `b` **only when `a` is `null` or `undefined`** — unlike `||`,\nwhich falls back on **any** falsy value (`0`, `''`, `false`). This makes `??`\ncorrect for defaults where `0`\u002F`''` are valid.\n\n```js\nconst count = 0\ncount || 10   \u002F\u002F 10  treats valid 0 as \"missing\"\ncount ?? 10   \u002F\u002F 0   only null\u002Fundefined trigger the default\n\nconst name = '' ?? 'anon' \u002F\u002F '' (empty string is kept)\n```\n\nUse `??` when only \"absent\" should trigger the fallback. You can't mix `??`\ndirectly with `&&`\u002F`||` without parentheses (a syntax error by design).\n",{"id":2186,"difficulty":96,"q":2187,"a":2188},"optional-chaining","What is optional chaining (?.)?","`?.` short-circuits to `undefined` if the value before it is `null`\u002F`undefined`,\ninstead of throwing — letting you safely access deep properties, call maybe-\nmissing methods, and index possibly-absent values.\n\n```js\nuser?.address?.city        \u002F\u002F undefined if user or address is null\nuser?.getName?.()          \u002F\u002F calls only if getName exists\narr?.[0]                   \u002F\u002F safe index access\n```\n\nIt pairs naturally with `??`: `user?.name ?? 'anon'`. Note it stops at the first\nnullish link and only guards against `null`\u002F`undefined` — not other errors.\n",{"id":2190,"difficulty":88,"q":2191,"a":2192},"array-equality","How do you compare two arrays or objects for equality?","`===` compares **references**, so two distinct arrays\u002Fobjects with identical\ncontents are **not** equal. You must compare contents yourself.\n\n```js\n[1, 2] === [1, 2]   \u002F\u002F false (different references)\n\n\u002F\u002F shallow array compare:\nconst eq = (a, b) => a.length === b.length && a.every((v, i) => v === b[i])\n\u002F\u002F quick (but flawed) deep compare:\nJSON.stringify(a) === JSON.stringify(b) \u002F\u002F order\u002Fundefined-sensitive\n```\n\n`JSON.stringify` works for simple data but breaks on key order, `undefined`,\nfunctions, and cycles. For robust deep equality, use a library (lodash\n`isEqual`).\n",{"id":2194,"difficulty":96,"q":2195,"a":2196},"string-number-conversion","What are the ways to convert a string to a number?","Several, with different strictness:\n\n```js\nNumber('42')     \u002F\u002F 42      (whole string; '' -> 0, '4a' -> NaN)\nparseInt('42px', 10) \u002F\u002F 42  (leading integer)\nparseFloat('3.14m') \u002F\u002F 3.14 (leading float)\n+'42'            \u002F\u002F 42      (unary plus — concise coercion)\n'42' * 1         \u002F\u002F 42      (arithmetic coercion)\n```\n\n`Number()`\u002Funary `+` are strict (invalid -> `NaN`); `parseInt`\u002F`parseFloat` are\nlenient (parse a prefix). Always validate with `Number.isNaN` afterward when the\ninput is untrusted.\n",{"id":2198,"difficulty":96,"q":2199,"a":2200},"boolean-double-bang","What does the double-bang (!!) operator do?","`!!x` coerces any value to its **boolean** equivalent. The first `!` converts to\nthe inverted boolean, the second `!` flips it back — giving the truthiness as a\nreal `true`\u002F`false`.\n\n```js\n!!'hello'   \u002F\u002F true\n!!0         \u002F\u002F false\n!!null      \u002F\u002F false\n!![]        \u002F\u002F true  (empty array is truthy)\nBoolean('hello') \u002F\u002F true — equivalent, more explicit\n```\n\nIt's a common idiom to normalize a value to a strict boolean (e.g. before\nreturning from a predicate or storing a flag). `Boolean(x)` does the same thing\nmore readably.\n",{"id":2202,"difficulty":88,"q":2203,"a":2204},"symbol","What is a Symbol and what is it used for?","A `Symbol` is a **unique, immutable** primitive, mainly used as **non-colliding\nobject keys**. Every `Symbol()` is distinct, even with the same description.\n\n```js\nconst id = Symbol('id')\nconst obj = { [id]: 123 }\nobj[id]              \u002F\u002F 123\nSymbol('x') === Symbol('x') \u002F\u002F false — always unique\n```\n\nUses: private-ish keys (not enumerable in `for...in`\u002F`JSON.stringify`), and\n**well-known symbols** that customize behavior (`Symbol.iterator`,\n`Symbol.toPrimitive`, `Symbol.asyncIterator`). `Symbol.for('k')` accesses a\nshared global registry.\n",{"id":2206,"difficulty":161,"q":2207,"a":2208},"array-coercion","How do arrays coerce to primitives?","An array's `toString` joins its elements with commas. So an empty array becomes\n`''`, a single-element array becomes that element's string, and `+` with a string\nconcatenates — leading to several classic surprises.\n\n```js\n[] + []        \u002F\u002F ''        (both -> '')\n[] + {}        \u002F\u002F '[object Object]'\n[1, 2] + [3]   \u002F\u002F '1,23'    ('1,2' + '3')\nNumber([])     \u002F\u002F 0         ('' -> 0)\nNumber([5])    \u002F\u002F 5         ('5' -> 5)\nNumber([1, 2]) \u002F\u002F NaN       ('1,2' -> NaN)\n```\n\nThese underpin the `[] == ![]` brain-teasers. The rule: array -> string (comma\njoin) -> then number if needed.\n",{"id":2210,"difficulty":88,"q":2211,"a":2212},"nan-operations","Which operations produce NaN?","`NaN` results from **invalid or undefined mathematical operations** — converting\nnon-numeric strings, `0\u002F0`, `Infinity - Infinity`, or arithmetic on `undefined`.\nAnd `NaN` is **contagious**: any arithmetic with it yields `NaN`.\n\n```js\nNumber('abc')          \u002F\u002F NaN\n0 \u002F 0                  \u002F\u002F NaN\nMath.sqrt(-1)          \u002F\u002F NaN\nundefined + 1          \u002F\u002F NaN\nparseInt('xyz', 10)    \u002F\u002F NaN\nNaN + 5                \u002F\u002F NaN (propagates)\n```\n\nBecause it spreads, a single bad value can turn a whole calculation into `NaN` —\nguard inputs and check with `Number.isNaN`.\n",{"id":2214,"difficulty":88,"q":2215,"a":2216},"undefined-not-defined","What is the difference between undefined and \"not defined\"?","**`undefined`** is a value: a declared variable that hasn't been assigned, or a\nmissing property. **\"Not defined\"** means the identifier doesn't exist at all —\naccessing it throws a **`ReferenceError`**.\n\n```js\nlet a\nconsole.log(a)         \u002F\u002F undefined (declared, no value)\nconsole.log(b)         \u002F\u002F ReferenceError: b is not defined\n\nconst obj = {}\nconsole.log(obj.x)     \u002F\u002F undefined (missing property, no error)\n```\n\nSo `undefined` is recoverable (it's just a value); a \"not defined\" reference is an\nerror. `typeof` is the safe way to check the latter without throwing.\n",{"id":2218,"difficulty":88,"q":2219,"a":2220},"typeof-undeclared","Why doesn't typeof throw on an undeclared variable?","`typeof` is special-cased to **not throw** a `ReferenceError` for an undeclared\nidentifier — it returns `'undefined'`. This makes it the safe way to feature-\ndetect a global that may not exist.\n\n```js\ntypeof someUndeclaredVar  \u002F\u002F 'undefined' (no error)\nsomeUndeclaredVar         \u002F\u002F ReferenceError\n\n\u002F\u002F safe environment checks:\nif (typeof window !== 'undefined') { \u002F* browser *\u002F }\n```\n\nCaveat: this leniency does **not** apply to `let`\u002F`const` in the temporal dead\nzone — `typeof x` before a `let x` declaration still throws.\n",{"id":2222,"difficulty":88,"q":2223,"a":2224},"immutable-primitives","What does it mean that primitives are immutable?","A primitive value itself can never be changed — operations that look like\nmutation actually create a **new** value. You can reassign the variable, but the\noriginal primitive is untouched.\n\n```js\nlet s = 'hello'\ns.toUpperCase()  \u002F\u002F 'HELLO' (a new string)\nconsole.log(s)   \u002F\u002F 'hello' (original unchanged)\ns[0] = 'J'       \u002F\u002F silently fails (or throws in strict mode)\ns = 'world'      \u002F\u002F reassigning the variable is fine\n```\n\nContrast objects\u002Farrays, which are mutable (you can change their contents in\nplace). Immutability is why primitives compare by value and are safe to share.\n",{"id":2226,"difficulty":88,"q":2227,"a":2228},"string-comparison","How does JavaScript compare strings with \u003C and >?","Relational operators compare strings **lexicographically** by UTF-16 code unit,\ncharacter by character. This is case-sensitive (uppercase letters have lower code\npoints than lowercase) and not locale-aware.\n\n```js\n'apple' \u003C 'banana'  \u002F\u002F true\n'Z' \u003C 'a'           \u002F\u002F true  (90 \u003C 97)\n'10' \u003C '9'          \u002F\u002F true  (string compare: '1' \u003C '9')\n'10' \u003C 9            \u002F\u002F false (mixed -> numeric: 10 \u003C 9)\n```\n\nFor human-friendly, locale-aware ordering (accents, case-insensitive), use\n`a.localeCompare(b)`. Note mixed string\u002Fnumber comparisons coerce to numbers.\n",{"id":2230,"difficulty":161,"q":2231,"a":2232},"deep-vs-shallow-equality","What is the difference between shallow and deep equality?","**Shallow** equality compares the top level: same reference, or matching primitive\nvalues \u002F first-level properties. **Deep** equality recursively compares nested\nstructures for equivalent contents.\n\n```js\nconst a = { x: { y: 1 } }\nconst b = { x: { y: 1 } }\na.x === b.x          \u002F\u002F false (different nested references)\n\u002F\u002F shallow: equal keys but nested refs differ -> not equal\n\u002F\u002F deep: recursively equal -> equal\n```\n\nReact uses shallow comparison for re-render decisions (props\u002Fstate), which is why\nmutating nested objects can be missed. Deep equality (lodash `isEqual`) is\ncostlier but compares full structure.\n",{"description":86},"JavaScript interview questions on primitive types, type coercion, == vs ===, truthy\u002Ffalsy values and checking types, with examples.","javascript\u002Ffundamentals\u002Fdata-types-coercion","Data Types & Coercion","vp9_844foLQtkq0K684OgyEhpivBJuIJMeUrLOlNC0k",{"id":2239,"title":2240,"body":2241,"description":86,"difficulty":96,"extension":89,"framework":10,"frameworkSlug":8,"meta":2245,"navigation":91,"order":11,"path":2246,"questions":2247,"related":224,"seo":2380,"seoDescription":2381,"stem":2382,"subtopic":2383,"topic":20,"topicSlug":21,"updated":789,"__hash__":2384},"qa\u002Fjavascript\u002Ffundamentals\u002Fvariables-scope-hoisting.md","Variables Scope Hoisting",{"type":83,"value":2242,"toc":2243},[],{"title":86,"searchDepth":29,"depth":29,"links":2244},[],{},"\u002Fjavascript\u002Ffundamentals\u002Fvariables-scope-hoisting",[2248,2252,2256,2260,2264,2268,2272,2276,2280,2284,2288,2292,2296,2300,2304,2308,2312,2316,2320,2324,2328,2332,2336,2340,2344,2348,2352,2356,2360,2364,2368,2372,2376],{"id":2249,"difficulty":96,"q":2250,"a":2251},"var-let-const","What is the difference between var, let and const?","They differ along three axes: **scope**, **hoisting\u002Finitialization**, and\n**reassignment**.\n\n| Keyword | Scope    | Hoisted? | Reassignable? | Redeclarable? |\n| ------- | -------- | -------- | ------------- | ------------- |\n| `var`   | function | yes, init `undefined` | yes | yes |\n| `let`   | block    | yes, in TDZ (uninit)  | yes | no  |\n| `const` | block    | yes, in TDZ (uninit)  | no  | no  |\n\nThe subtle one is `const`: it makes the **binding** constant, **not the\nvalue**. You can't reassign the variable, but if it holds an object or array\nyou can still mutate the contents.\n\n```js\nconst user = { name: 'Ada' }\nuser.name = 'Grace' \u002F\u002F OK — mutating the object the binding points to\nuser = {}           \u002F\u002F TypeError — reassigning the binding\n\nconst list = [1, 2]\nlist.push(3)        \u002F\u002F [1, 2, 3]\n```\n\nModern guidance: default to `const`, use `let` when you genuinely need to\nreassign, and avoid `var`.\n",{"id":2253,"difficulty":88,"q":2254,"a":2255},"hoisting","What is hoisting?","Hoisting is the JavaScript engine processing **declarations** before executing\ncode, so they behave as if \"moved\" to the top of their scope. But *what* gets\nhoisted differs:\n\n- `var` declarations are hoisted **and initialized to `undefined`**, so reading\n  one before its assignment gives `undefined` (no error).\n- **Function declarations** are hoisted **entirely** — you can call them above\n  where they're written.\n- `let`\u002F`const` are hoisted **but left uninitialized** in the *temporal dead\n  zone*; touching them early throws.\n\n```js\nconsole.log(a) \u002F\u002F undefined  (var hoisted, value not yet assigned)\nvar a = 1\n\ngreet()        \u002F\u002F 'hi'  (function declaration fully hoisted)\nfunction greet() { return 'hi' }\n\nconsole.log(b) \u002F\u002F ReferenceError (TDZ)\nlet b = 2\n```\n\nMental model: declarations are \"registered\" first; only the **assignments**\nrun in place.\n",{"id":2257,"difficulty":88,"q":2258,"a":2259},"tdz","What is the temporal dead zone (TDZ)?","The TDZ is the window between **entering a scope** and the line where a\n`let`\u002F`const` variable is actually **declared**. The binding exists (it was\nhoisted) but is *uninitialized*, so any attempt to read or write it in that\nwindow throws a `ReferenceError`.\n\n```js\n{\n  \u002F\u002F TDZ for `x` starts here\n  console.log(x) \u002F\u002F ReferenceError: Cannot access 'x' before initialization\n  let x = 5      \u002F\u002F TDZ ends — x is now initialized\n  console.log(x) \u002F\u002F 5\n}\n```\n\nIt exists on purpose: it turns \"used before declared\" from a silent\n`undefined` bug (the `var` behavior) into a **loud, immediate error**, which\ncatches mistakes earlier and makes `const` semantics sound.\n",{"id":2261,"difficulty":96,"q":2262,"a":2263},"block-scope","What is the difference between block scope and function scope?","**Function scope** (`var`) means a variable is visible **anywhere inside the\nenclosing function**, regardless of which `{ }` blocks it's nested in. **Block\nscope** (`let`\u002F`const`) confines a variable to the **nearest pair of braces** —\nincluding `if`, `for`, `while`, and even a bare `{ }` block.\n\n```js\nfunction demo() {\n  if (true) {\n    var v = 'function-scoped'\n    let l = 'block-scoped'\n  }\n  console.log(v) \u002F\u002F 'function-scoped' — var leaks out of the if\n  console.log(l) \u002F\u002F ReferenceError — l only exists inside the if\n}\n```\n\nBlock scoping is generally safer: variables stay where they're relevant and\nyou avoid accidental leakage across a function — which is one big reason `let`\u002F\n`const` replaced `var`.\n",{"id":2265,"difficulty":96,"q":2266,"a":2267},"redeclare","Can you redeclare variables in the same scope?","`var` lets you **redeclare** the same name in the same scope without\ncomplaint — which silently masks bugs and accidental overwrites. `let` and\n`const` **throw a `SyntaxError`** if you redeclare an identifier in the same\nscope.\n\n```js\nvar x = 1\nvar x = 2      \u002F\u002F allowed (and easy to do by accident)\n\nlet y = 1\nlet y = 2      \u002F\u002F SyntaxError: Identifier 'y' has already been declared\n```\n\nNote this is about *redeclaration in the same scope*. You can still\n**shadow** a `let` in a nested inner block with a new `let` of the same name —\nthat creates a separate binding and is perfectly legal.\n",{"id":2269,"difficulty":88,"q":2270,"a":2271},"global-this","Do var, let and const create properties on the global object?","At the **top level** of a script, a `var` declaration *also* creates a property\non the global object (`window` in browsers, `globalThis` generally). `let` and\n`const` do **not** — they create bindings in a separate *script-scoped* record\nthat the global object can't see.\n\n```js\nvar a = 1\nlet b = 2\nconst c = 3\n\nwindow.a \u002F\u002F 1          \u003C- var leaked onto the global object\nwindow.b \u002F\u002F undefined  \u003C- let did not\nwindow.c \u002F\u002F undefined\n```\n\nThis is another reason to avoid top-level `var`: it pollutes the global\nnamespace and can clash with other scripts or built-ins. (Inside ES modules,\neven top-level `var` doesn't attach to the global object, since module scope\nisn't global scope.)\n",{"id":2273,"difficulty":161,"q":2274,"a":2275},"loop-closure","Why does var behave unexpectedly in a for loop with closures?","Because `var` is **function-scoped**, the loop reuses **one single binding**\nacross all iterations. Any callbacks created in the loop close over that *same*\nvariable, so when they run later they all read its **final value**. `let`\ncreates a **fresh binding each iteration**, so each closure captures its own\ncopy.\n\n```js\nfor (var i = 0; i \u003C 3; i++) setTimeout(() => console.log(i)) \u002F\u002F 3 3 3\nfor (let j = 0; j \u003C 3; j++) setTimeout(() => console.log(j)) \u002F\u002F 0 1 2\n```\n\nWith `var`, by the time the timers fire the loop has long finished and `i` is\n`3`. With `let`, the language re-binds `j` per iteration (and even copies the\nvalue forward for the increment), giving each callback `0`, `1`, `2`. The\npre-`let` fix was an IIFE to manufacture a new scope each pass.\n",{"id":2277,"difficulty":96,"q":2278,"a":2279},"const-array","Can you modify an array declared with const?","Yes. `const` freezes the **binding**, not the **value**. The variable must keep\npointing at the same array, but the array's contents are fully mutable.\n\n```js\nconst arr = [1, 2, 3]\narr.push(4)      \u002F\u002F [1, 2, 3, 4]\narr[0] = 99      \u002F\u002F [99, 2, 3, 4]\narr.length = 0   \u002F\u002F [] — still the same array\narr = []         \u002F\u002F TypeError: Assignment to constant variable\n```\n\nIf you want the *contents* to be immutable too, that's a separate concern —\nuse `Object.freeze(arr)` for a shallow freeze (and note `freeze` is shallow, so\nnested objects can still change).\n",{"id":2281,"difficulty":88,"q":2282,"a":2283},"lexical-scope","What is lexical scope?","Lexical (static) scope means a variable's accessibility is determined by **where\nit's written** in the source code — the nesting of functions\u002Fblocks — not by where\nor how a function is called. The structure is fixed at author time.\n\n```js\nconst outer = 1\nfunction f() {\n  const inner = 2\n  function g() { return outer + inner } \u002F\u002F sees both by lexical nesting\n  return g()\n}\nf() \u002F\u002F 3\n```\n\nBecause scope is determined by position, you can tell what any function can access\njust by reading the code. JavaScript uses lexical scope (unlike languages with\ndynamic scope).\n",{"id":2285,"difficulty":88,"q":2286,"a":2287},"scope-chain","What is the scope chain?","When you reference a variable, the engine looks in the **current scope**, then its\n**enclosing scope**, and so on outward until the global scope — this series of\nlinked scopes is the scope chain. The first match wins; if none is found, it's a\n`ReferenceError`.\n\n```js\nconst a = 'global'\nfunction outer() {\n  const b = 'outer'\n  function inner() {\n    const c = 'inner'\n    return `${a} ${b} ${c}` \u002F\u002F resolves c->inner, b->outer, a->global\n  }\n  return inner()\n}\n```\n\nLookups go **inward-to-outward only** — an outer scope can't see inner variables.\nThis chain is also what closures preserve.\n",{"id":2289,"difficulty":88,"q":2290,"a":2291},"shadowing","What is variable shadowing?","Shadowing is declaring a variable in an inner scope with the **same name** as one\nin an outer scope. The inner variable \"shadows\" the outer one within that scope;\nthe outer remains unchanged outside.\n\n```js\nconst x = 1\nfunction f() {\n  const x = 2   \u002F\u002F shadows the outer x\n  console.log(x) \u002F\u002F 2\n}\nf()\nconsole.log(x)  \u002F\u002F 1 (outer untouched)\n```\n\nShadowing is legal and sometimes useful, but accidental shadowing causes bugs.\nNote you **can't** shadow with `var`\u002F`let` in a way that accesses the outer value\nmid-declaration (TDZ), and linters can warn on shadowing.\n",{"id":2293,"difficulty":161,"q":2294,"a":2295},"fn-decl-vs-block","How are function declarations scoped inside blocks?","In **strict mode** (the default in modules\u002Fclasses), a function declaration inside\na block is **block-scoped** — visible only within that block. In sloppy mode the\nbehavior is inconsistent across engines, which is a common gotcha.\n\n```js\n'use strict'\nif (true) {\n  function foo() { return 1 }\n}\ntypeof foo \u002F\u002F 'undefined' in strict mode — block-scoped\n```\n\nBest practice: don't declare functions inside blocks. Use a **function\nexpression** assigned to a `let`\u002F`const` if you need a conditionally-defined\nfunction, for predictable scoping.\n",{"id":2297,"difficulty":161,"q":2298,"a":2299},"let-switch","Why can let and const be tricky in a switch statement?","A `switch` has **one shared block scope** across all its `case`s. Declaring\n`let`\u002F`const` in one case puts it in the TDZ for the entire switch, so another case\ncan hit a `ReferenceError` or a redeclaration `SyntaxError`.\n\n```js\nswitch (x) {\n  case 1:\n    let y = 'a'   \u002F\u002F y is scoped to the whole switch\n    break\n  case 2:\n    let y = 'b'   \u002F\u002F SyntaxError: 'y' already declared\n    break\n}\n```\n\nFix by wrapping each case body in its own **block** `{ ... }`, giving each `case`\na separate scope.\n",{"id":2301,"difficulty":88,"q":2302,"a":2303},"fn-expr-hoist","Are function expressions hoisted?","The **variable** is hoisted, but the **function value is not** — only the\ndeclaration is. So calling a function expression before its assignment fails\n(`undefined`\u002FTDZ), unlike a function declaration which is fully hoisted.\n\n```js\ndeclared()  \u002F\u002F works — declaration hoisted\nfunction declared() {}\n\nexpressed() \u002F\u002F TypeError: expressed is not a function (var) \u002F ReferenceError (let)\nvar expressed = function () {}\n```\n\nSo function **declarations** are callable above their line; function\n**expressions** (including arrows) follow normal variable hoisting rules and\naren't.\n",{"id":2305,"difficulty":161,"q":2306,"a":2307},"class-hoist","Are class declarations hoisted?","Class declarations **are hoisted** but, like `let`\u002F`const`, remain in the\n**temporal dead zone** — so you **can't use a class before its declaration**.\nUnlike function declarations, they aren't callable early.\n\n```js\nnew Foo()  \u002F\u002F ReferenceError: Cannot access 'Foo' before initialization\nclass Foo {}\n\nbar()      \u002F\u002F function declarations work\nfunction bar() {}\n```\n\nSo \"classes are hoisted\" is technically true, but the TDZ means it behaves like\nnot-hoisted in practice. Always declare classes before using them.\n",{"id":2309,"difficulty":161,"q":2310,"a":2311},"named-fn-expr","What is a named function expression and why use one?","A named function expression gives the function a name that's **only visible inside\nits own body** (not the outer scope). It's useful for self-reference (recursion)\nand clearer stack traces.\n\n```js\nconst factorial = function fact(n) {\n  return n \u003C= 1 ? 1 : n * fact(n - 1) \u002F\u002F `fact` usable inside\n}\nfactorial(5) \u002F\u002F 120\nfact          \u002F\u002F ReferenceError — not visible outside\n```\n\nThe inner name is safer than relying on the outer variable (which could be\nreassigned) and shows up in debuggers instead of \"anonymous.\"\n",{"id":2313,"difficulty":96,"q":2314,"a":2315},"nested-scope-lookup","How does variable lookup work in nested functions?","An inner function can read variables from all of its enclosing scopes, resolved\nvia the scope chain. Each function adds a scope; lookups proceed outward until a\nmatch or the global scope.\n\n```js\nfunction a() {\n  let x = 1\n  function b() {\n    let y = 2\n    function c() { return x + y } \u002F\u002F reaches up two levels\n    return c()\n  }\n  return b()\n}\na() \u002F\u002F 3\n```\n\nInner scopes see outer variables, never the reverse. This nested visibility is the\nfoundation of closures.\n",{"id":2317,"difficulty":161,"q":2318,"a":2319},"implicit-global","What is an accidental (implicit) global variable?","Assigning to a variable **without declaring** it (`x = 5`) in sloppy mode creates\na property on the **global object** instead of erroring — a common source of bugs\nand leaks. **Strict mode** throws a `ReferenceError` instead.\n\n```js\nfunction f() {\n  count = 1   \u002F\u002F no var\u002Flet\u002Fconst -> implicit global\n}\nf()\nconsole.log(count) \u002F\u002F 1 (leaked to global!)\n\n\u002F\u002F strict mode:\n'use strict'\nfunction g() { total = 1 } \u002F\u002F ReferenceError\n```\n\nAlways declare variables, and use strict mode (automatic in modules) so this\nmistake fails loudly.\n",{"id":2321,"difficulty":88,"q":2322,"a":2323},"strict-mode-vars","How does strict mode change variable behavior?","Strict mode tightens several variable rules: assigning to an undeclared variable\n**throws** (no accidental globals), you can't `delete` a variable, duplicate\nparameter names are errors, and `this` is `undefined` instead of the global object\nin plain calls.\n\n```js\n'use strict'\nundeclared = 5   \u002F\u002F ReferenceError\nfunction dup(a, a) {} \u002F\u002F SyntaxError\n```\n\nES modules and class bodies are **always** strict. Strict mode surfaces bugs at\nauthor\u002Fparse time that would otherwise fail silently — a big reason modern code is\nstrict by default.\n",{"id":2325,"difficulty":96,"q":2326,"a":2327},"const-init","Why must a const be initialized at declaration?","Because `const` can be assigned **only once**, you must give it that value at\ndeclaration — there's no later opportunity to assign. Declaring without a value is\na `SyntaxError`.\n\n```js\nconst x = 5   \u002F\u002F\nconst y        \u002F\u002F SyntaxError: Missing initializer in const declaration\n```\n\n`let` and `var` can be declared without a value (defaulting to `undefined`), but\n`const`'s \"assign once\" contract requires the value up front. This also makes\n`const` ineligible for the classic split declare-then-assign pattern.\n",{"id":2329,"difficulty":161,"q":2330,"a":2331},"var-fn-clash","What happens when a var and a function declaration share a name?","During hoisting, **function declarations take precedence** over `var`\ndeclarations with the same name. The `var` declaration is ignored (its\nassignment, if any, still runs in place and can overwrite the function later).\n\n```js\nconsole.log(typeof foo) \u002F\u002F 'function' — function decl wins at hoist time\nvar foo = 'bar'\nfunction foo() {}\nconsole.log(typeof foo) \u002F\u002F 'string' — the assignment ran\n```\n\nSo at the top the name is the function; once execution reaches `foo = 'bar'`, it\nbecomes the string. These clashes are confusing — avoid reusing names.\n",{"id":2333,"difficulty":88,"q":2334,"a":2335},"module-scope","What is module scope?","Each ES module has its own **top-level scope** — variables declared at the top of\na module are **not** global; they're private to that module unless `export`ed.\nEven top-level `var` doesn't attach to the global object.\n\n```js\n\u002F\u002F module.js\nconst secret = 42       \u002F\u002F module-scoped, not global\nexport const api = {}   \u002F\u002F shared only via export\n\u002F\u002F window.secret -> undefined\n```\n\nThis is a major improvement over classic scripts, where top-level `var` polluted\nthe global namespace. Module scope plus strict mode is why modern code avoids many\nlegacy footguns.\n",{"id":2337,"difficulty":161,"q":2338,"a":2339},"let-per-iteration","How does let create a new binding each loop iteration?","In a `for` loop, `let` creates a **fresh binding per iteration** and copies the\nvalue forward — so closures created in the loop each capture their own copy. `var`\nshares one binding across all iterations.\n\n```js\nconst fns = []\nfor (let i = 0; i \u003C 3; i++) fns.push(() => i)\nfns.map(f => f())  \u002F\u002F [0, 1, 2]\n\nconst v = []\nfor (var j = 0; j \u003C 3; j++) v.push(() => j)\nv.map(f => f())    \u002F\u002F [3, 3, 3]\n```\n\nThis per-iteration binding is a deliberate `let` feature that fixes the\nlong-standing closure-in-loop bug.\n",{"id":2341,"difficulty":161,"q":2342,"a":2343},"tdz-typeof","Does typeof protect against the temporal dead zone?","No. `typeof` is safe for **undeclared** identifiers, but a `let`\u002F`const` variable\nin its **TDZ** is declared-but-uninitialized, so even `typeof` throws a\n`ReferenceError`.\n\n```js\ntypeof undeclaredVar  \u002F\u002F 'undefined' (safe)\n\ntypeof x              \u002F\u002F ReferenceError (x is in the TDZ)\nlet x = 1\n```\n\nSo the usual \"use `typeof` to safely check existence\" trick fails for block-scoped\nvariables before their declaration line. The TDZ deliberately makes\nuse-before-declaration an error.\n",{"id":2345,"difficulty":88,"q":2346,"a":2347},"bare-block","What is a bare block and how does it scope variables?","A bare block is a standalone `{ ... }` (not attached to `if`\u002F`for`\u002Fetc.). With\n`let`\u002F`const` it creates a **new block scope**, so variables inside are invisible\noutside — a lightweight way to limit scope. `var` ignores it (function-scoped).\n\n```js\n{\n  let secret = 42\n  var leaked = 1\n}\nconsole.log(leaked) \u002F\u002F 1 (var ignores the block)\nconsole.log(secret) \u002F\u002F ReferenceError (let is block-scoped)\n```\n\nBare blocks can also resolve `switch`\u002Ftemporary-variable naming conflicts by\nisolating declarations.\n",{"id":2349,"difficulty":88,"q":2350,"a":2351},"shadow-nested","Can you shadow a let variable in a nested block?","Yes. A nested block can declare a new `let`\u002F`const` with the same name, creating a\n**separate binding** that shadows the outer one within that block. This is\ndifferent from redeclaration in the **same** scope (which errors).\n\n```js\nlet x = 1\n{\n  let x = 2     \u002F\u002F shadows — different (nested) scope\n  console.log(x) \u002F\u002F 2\n}\nconsole.log(x)  \u002F\u002F 1\n\nlet y = 1\nlet y = 2       \u002F\u002F SyntaxError — same scope\n```\n\nShadowing across scopes is allowed; redeclaring in the same scope is not.\n",{"id":2353,"difficulty":161,"q":2354,"a":2355},"dynamic-vs-lexical","What is the difference between lexical and dynamic scoping?","- **Lexical scoping** (what JS uses): a function's free variables resolve based on\n  **where it's defined** in the source.\n- **Dynamic scoping** (some other languages): free variables resolve based on the\n  **call stack at runtime** — who called the function.\n\n```js\nlet x = 'global'\nfunction inner() { return x }\nfunction outer() { let x = 'outer'; return inner() }\nouter() \u002F\u002F 'global' — lexical: inner sees where it was DEFINED\n\u002F\u002F (a dynamically-scoped language would return 'outer')\n```\n\nJS's only \"dynamic\" feature is `this`, which is bound by the call site — but\nordinary variable lookup is always lexical.\n",{"id":2357,"difficulty":88,"q":2358,"a":2359},"hoisting-mechanism","What actually happens during hoisting (the two phases)?","JavaScript runs in two phases per scope: a **creation (compilation) phase** that\nregisters all declarations (allocating `var` as `undefined`, `let`\u002F`const` as\nuninitialized in the TDZ, functions fully), and an **execution phase** that runs\nthe code and performs assignments in order.\n\n```js\n\u002F\u002F creation phase registers: a (undefined), greet (function)\nconsole.log(a)  \u002F\u002F undefined\nvar a = 1       \u002F\u002F execution: a becomes 1\ngreet()         \u002F\u002F already callable\nfunction greet() {}\n```\n\nSo \"hoisting\" isn't physical code movement — it's declarations being processed\nbefore any line executes. Only assignments happen in place.\n",{"id":2361,"difficulty":88,"q":2362,"a":2363},"var-leak","Why is var leaking out of blocks a problem?","`var` is function-scoped, so a `var` declared inside an `if`\u002F`for`\u002Fblock is visible\nthroughout the **entire enclosing function** — leaking beyond where it's relevant,\nwhich causes accidental reuse and bugs.\n\n```js\nfunction f() {\n  for (var i = 0; i \u003C 3; i++) {}\n  console.log(i) \u002F\u002F 3 — i leaked out of the loop\n\n  if (true) { var temp = 'x' }\n  console.log(temp) \u002F\u002F 'x' — leaked out of the if\n}\n```\n\n`let`\u002F`const` confine variables to their block, keeping scope tight. This leakage\nis a primary reason to avoid `var`.\n",{"id":2365,"difficulty":161,"q":2366,"a":2367},"deep-freeze","How do you make an object deeply immutable?","`Object.freeze` is **shallow** — it freezes the top-level properties but nested\nobjects remain mutable. For deep immutability you must recursively freeze.\n\n```js\nconst obj = Object.freeze({ a: 1, nested: { b: 2 } })\nobj.a = 9          \u002F\u002F ignored (or throws in strict mode)\nobj.nested.b = 99  \u002F\u002F still mutable! freeze is shallow\n\nfunction deepFreeze(o) {\n  Object.values(o).forEach(v => v && typeof v === 'object' && deepFreeze(v))\n  return Object.freeze(o)\n}\n```\n\nCheck frozen status with `Object.isFrozen`. For shared constants, deep-freezing\nprevents accidental mutation.\n",{"id":2369,"difficulty":88,"q":2370,"a":2371},"iife-scope-isolation","How does an IIFE isolate scope?","An IIFE runs immediately and creates a **private function scope**, so variables\ninside never touch the enclosing\u002Fglobal scope. Before block scoping and modules, it\nwas the main tool to avoid polluting globals and to create private state.\n\n```js\n(function () {\n  var temp = 'private'   \u002F\u002F not global\n  \u002F\u002F setup work...\n})()\ntypeof temp \u002F\u002F 'undefined' — isolated\n```\n\nToday, block scope (`{ let ... }`) and ES modules cover most of these needs, but\nIIFEs still appear in bundled code and for one-off encapsulation.\n",{"id":2373,"difficulty":96,"q":2374,"a":2375},"let-vs-const-when","When should you use let vs const?","Default to **`const`** — it signals the binding won't be reassigned, preventing\naccidental reassignment and making code easier to reason about. Use **`let`** only\nwhen you genuinely need to reassign (counters, accumulators, reassigned in\nbranches). Avoid `var`.\n\n```js\nconst MAX = 100          \u002F\u002F never reassigned\nconst user = { id: 1 }   \u002F\u002F const, but you can still mutate the object\nlet total = 0            \u002F\u002F reassigned in a loop\nfor (const item of items) total += item.price\n```\n\n\"const by default, let when needed\" is the widely-adopted convention. Remember\n`const` blocks reassignment, not mutation.\n",{"id":2377,"difficulty":88,"q":2378,"a":2379},"global-pollution","Why are global variables discouraged?","Globals are accessible and mutable from **anywhere**, so they create hidden\ncoupling, name collisions between scripts\u002Flibraries, hard-to-trace bugs, and\nproblems in concurrent\u002Ftesting contexts. Any code can change them unexpectedly.\n\n```js\n\u002F\u002F global state anyone can clobber\nvar config = {}\n\u002F\u002F encapsulate in a module or closure\nexport const config = createConfig()\n```\n\nMinimize globals by using **modules** (module scope), closures, and passing\ndependencies explicitly. When a true global is needed, namespace it under a single\nobject to limit collisions.\n",{"description":86},"Common JavaScript interview questions on var, let and const, scope, hoisting and the temporal dead zone, with clear answers and examples.","javascript\u002Ffundamentals\u002Fvariables-scope-hoisting","Variables, Scope & Hoisting","1OhvPeamj0K5ICmSSBRUFJ9iY7c4aoSeIv0ARSpSdac",{"id":2386,"title":2387,"body":2388,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":2392,"navigation":91,"order":11,"path":2393,"questions":2394,"related":224,"seo":2518,"seoDescription":2519,"stem":2520,"subtopic":2521,"topic":73,"topicSlug":75,"updated":228,"__hash__":2522},"qa\u002Fjavascript\u002Fmodern\u002Fdestructuring-spread-rest.md","Destructuring Spread Rest",{"type":83,"value":2389,"toc":2390},[],{"title":86,"searchDepth":29,"depth":29,"links":2391},[],{},"\u002Fjavascript\u002Fmodern\u002Fdestructuring-spread-rest",[2395,2399,2403,2407,2410,2414,2417,2421,2425,2429,2433,2437,2441,2444,2448,2452,2456,2460,2463,2467,2471,2475,2479,2483,2487,2491,2494,2498,2502,2506,2510,2514],{"id":2396,"difficulty":96,"q":2397,"a":2398},"what-is-destructuring","What is destructuring in JavaScript?","**Destructuring** is syntax that unpacks values from objects (or arrays) into\ndistinct variables in a single expression. It replaces repetitive\nproperty-by-property assignment with a compact pattern that mirrors the shape\nof the data.\n\nThe mechanism: the **pattern** on the left of `=` is matched against the\n**value** on the right, binding each name to the corresponding property.\n\n```js\nconst user = { name: 'Ada', age: 36 }\nconst { name, age } = user           \u002F\u002F two variables in one line\nconsole.log(name, age)               \u002F\u002F 'Ada' 36\n\u002F\u002F verbose old way:\n\u002F\u002F const name = user.name; const age = user.age\n```\n\nPitfall: destructuring **reads** properties — it does not mutate the source\nobject. `user` is untouched after the line above.\n",{"id":2400,"difficulty":96,"q":2401,"a":2402},"object-destructuring-basics","How does object destructuring match variables to properties?","It matches **by property name**, not by position (unlike array destructuring).\nThe variable name must equal the key you want to extract.\n\n```js\nconst point = { x: 1, y: 2 }\nconst { y, x } = point               \u002F\u002F order doesn't matter\nconsole.log(x, y)                    \u002F\u002F 1 2\nconst { z } = point                  \u002F\u002F z is undefined (no such key)\n```\n\nPitfall: because matching is by name, a typo silently produces `undefined`\nrather than an error — there is no \"this key doesn't exist\" warning.\n",{"id":2404,"difficulty":96,"q":2405,"a":2406},"rename-while-destructuring","How do you rename a variable while destructuring an object?","Use the `key: newName` syntax. The left side of the colon is the **property to\nread**; the right side is the **local variable** to bind it to.\n\n```js\nconst res = { status: 200, data: 'ok' }\nconst { status: code, data: body } = res   \u002F\u002F rename both\nconsole.log(code, body)                     \u002F\u002F 200 'ok'\n\u002F\u002F console.log(status)                      \u002F\u002F ReferenceError — status not defined\n```\n\nThe original key name (`status`) is **not** in scope afterward — only the new\nname is. Pitfall: people read `status: code` as \"assign status to code\" but it's\nthe reverse — read `status`, name it `code`.\n",{"id":249,"difficulty":96,"q":2408,"a":2409},"How do default values work in object destructuring?","A default after `=` is applied only when the extracted value is **`undefined`**\n(a missing key or an explicit `undefined`). Any other value — including `null`,\n`0`, `''`, or `false` — is kept as-is.\n\n```js\nconst { timeout = 1000, retries = 3 } = { retries: 0 }\nconsole.log(timeout, retries)        \u002F\u002F 1000 0  0 is kept, default not applied\nconst { x = 5 } = { x: null }\nconsole.log(x)                       \u002F\u002F null  default NOT used — null isn't undefined\n```\n\nPitfall: defaults trigger only on `undefined`, so `null` slips through. If you\nneed a fallback for `null` too, combine with `??` after extracting.\n",{"id":2411,"difficulty":88,"q":2412,"a":2413},"rename-and-default","How do you combine renaming and a default value?","Stack the two syntaxes: `key: newName = default`. JavaScript reads `key`,\nbinds it to `newName`, and falls back to `default` if that value is `undefined`.\n\n```js\nconst settings = {}\nconst { mode: displayMode = 'light' } = settings\nconsole.log(displayMode)             \u002F\u002F 'light'  renamed AND defaulted\n```\n\nThe order is fixed: property name, then colon and new name, then equals and\ndefault. Pitfall: writing `mode = 'light': displayMode` is a syntax error — the\ndefault attaches to the renamed binding, after the colon.\n",{"id":257,"difficulty":88,"q":2415,"a":2416},"How do you destructure nested objects?","Nest a pattern wherever a value would be a sub-object. The colon here means\n\"descend into this object\" rather than \"rename\".\n\n```js\nconst user = { name: 'Ada', address: { city: 'London', zip: 'SW1' } }\nconst { address: { city } } = user\nconsole.log(city)                    \u002F\u002F 'London'\n\u002F\u002F console.log(address)              \u002F\u002F ReferenceError — address itself not bound\n```\n\nTwo gotchas: (1) the intermediate name (`address`) is **not** created as a\nvariable — only the leaf (`city`) is. (2) If `address` were `undefined`,\ndestructuring into it throws **`TypeError: Cannot destructure property 'city'\nof undefined`** — add a default: `{ address: { city } = {} }`.\n",{"id":2418,"difficulty":161,"q":2419,"a":2420},"computed-property-destructuring","How do you destructure a property whose key is computed at runtime?","Use **computed key** syntax `[expr]: target`. The bracketed expression is\nevaluated to a string key, and you must supply a binding name after the colon\n(there's no implicit name to infer).\n\n```js\nconst field = 'email'\nconst record = { email: 'a@b.com', name: 'Ada' }\nconst { [field]: value } = record\nconsole.log(value)                   \u002F\u002F 'a@b.com'  dynamic key extracted\n```\n\nPitfall: you **must** name the target (`: value`) — `const { [field] } = record`\nis a syntax error because the engine can't derive a variable name from an\narbitrary expression.\n",{"id":2422,"difficulty":88,"q":2423,"a":2424},"destructuring-params","How do you destructure function parameters?","Put the pattern directly in the parameter list. The caller passes one object and\nthe function pulls out named fields — a common alternative to long positional\nargument lists.\n\n```js\nfunction createUser({ name, role = 'user', active = true }) {\n  return `${name}:${role}:${active}`\n}\ncreateUser({ name: 'Ada', role: 'admin' })   \u002F\u002F 'Ada:admin:true'\n```\n\nThis gives named, order-independent arguments with per-field defaults. Pitfall:\ncalling `createUser()` with **no argument** throws, because you can't destructure\n`undefined`. Guard with a default: `function createUser({ ... } = {})`.\n",{"id":2426,"difficulty":88,"q":2427,"a":2428},"param-default-object","Why give a destructured parameter a default of {}?","Destructuring `undefined` throws a `TypeError`. Defaulting the whole parameter to\n`{}` lets the function be called with **no argument** while still applying each\nfield's individual defaults.\n\n```js\nfunction connect({ host = 'localhost', port = 5432 } = {}) {\n  return `${host}:${port}`\n}\nconnect()                            \u002F\u002F 'localhost:5432' — no throw\n\u002F\u002F without the = {}, connect() would throw TypeError\n```\n\nTwo levels of defaulting are at work: `= {}` guards the missing-object case, and\n`host = ...` \u002F `port = ...` guard missing fields. Pitfall: forgetting the outer\n`= {}` makes the function fragile to no-arg calls.\n",{"id":2430,"difficulty":88,"q":2431,"a":2432},"rest-in-object-destructuring","What does the rest pattern do in object destructuring?","`...rest` collects all **remaining own enumerable** properties not already named\ninto a new object. It's how you extract a few fields and keep the rest grouped.\n\n```js\nconst props = { id: 1, name: 'Ada', role: 'admin' }\nconst { id, ...rest } = props\nconsole.log(id)                      \u002F\u002F 1\nconsole.log(rest)                    \u002F\u002F { name: 'Ada', role: 'admin' }  new object\n```\n\nThe rest object is a **new shallow object**, distinct from the source. Pitfall:\nthe rest element must be **last** — `const { ...rest, id }` is a syntax error.\n",{"id":2434,"difficulty":88,"q":2435,"a":2436},"rest-omit-property","How do you create a copy of an object without a particular property?","Name the property to drop, then capture `...rest`. The named binding is discarded\nand `rest` holds everything else — an immutable \"omit\" pattern.\n\n```js\nconst user = { id: 1, password: 'secret', name: 'Ada' }\nconst { password, ...safe } = user\nconsole.log(safe)                    \u002F\u002F { id: 1, name: 'Ada' }  password removed\n\u002F\u002F user is unchanged — original still has password\n```\n\nThis is purely a copy; the original is untouched. Pitfall: `password` is now an\nunused variable in scope — some linters flag it; an underscore prefix or\n`\u002F\u002F eslint-disable` comment is the usual fix.\n",{"id":2438,"difficulty":96,"q":2439,"a":2440},"object-spread-basics","What does the object spread operator do?","`...obj` inside an object literal copies that object's **own enumerable**\nproperties into the new object. It's the concise way to clone or extend.\n\n```js\nconst base = { a: 1, b: 2 }\nconst copy = { ...base }             \u002F\u002F shallow clone\nconst extended = { ...base, c: 3 }   \u002F\u002F add a property\nconsole.log(extended)                \u002F\u002F { a: 1, b: 2, c: 3 }\n```\n\nSpread only copies **own** enumerable properties — inherited (prototype) and\nnon-enumerable properties are skipped. Pitfall: it's a **shallow** copy, so\nnested objects are shared by reference, not duplicated.\n",{"id":273,"difficulty":96,"q":2442,"a":2443},"How do you merge two objects with spread?","List both with `...` in one literal. Properties are copied left-to-right, so a\nlater object's values **override** earlier ones for duplicate keys.\n\n```js\nconst defaults = { theme: 'light', size: 'md' }\nconst overrides = { size: 'lg' }\nconst config = { ...defaults, ...overrides }\nconsole.log(config)                  \u002F\u002F { theme: 'light', size: 'lg' }\n```\n\nThe **last write wins** for any shared key. Pitfall: order matters — putting\n`...defaults` last would let defaults clobber your overrides, which is almost\nalways a bug.\n",{"id":2445,"difficulty":88,"q":2446,"a":2447},"spread-override-order","How does property precedence work when spreading and adding keys together?","The object literal is built **left to right**, and each later key with the same\nname overwrites the earlier one. This works whether the key comes from a spread\nor is written literally.\n\n```js\nconst obj = { a: 1 }\nconsole.log({ ...obj, a: 2 })        \u002F\u002F { a: 2 }  literal after spread wins\nconsole.log({ a: 2, ...obj })        \u002F\u002F { a: 1 }  spread after literal wins\n```\n\nPosition, not source type, decides the winner. Pitfall: spreading after your\nexplicit overrides silently undoes them — keep explicit keys after the spreads\nyou want them to win against.\n",{"id":2449,"difficulty":161,"q":2450,"a":2451},"shallow-copy-gotcha","Why is object spread only a shallow copy, and why does that matter?","Spread copies the top-level property **values**. When a value is an object, it\ncopies the **reference**, not a fresh clone — so nested objects are shared\nbetween the original and the copy.\n\n```js\nconst original = { name: 'Ada', meta: { active: true } }\nconst copy = { ...original }\ncopy.meta.active = false\nconsole.log(original.meta.active)    \u002F\u002F false  original mutated too!\ncopy.name = 'Bob'\nconsole.log(original.name)           \u002F\u002F 'Ada'  top-level is independent\n```\n\nTop-level properties are independent; nested ones are not. For a deep copy use\n`structuredClone(original)` (or libraries). Pitfall: mutating nested state on a\n\"copy\" silently corrupts the source — a frequent source of state bugs.\n",{"id":2453,"difficulty":88,"q":2454,"a":2455},"spread-vs-object-assign","What is the difference between spread and Object.assign?","Both do a shallow merge of own enumerable properties, but `Object.assign(target,\n...sources)` **mutates** `target` and returns it, whereas `{ ...a, ...b }`\nalways creates a **new** object.\n\n```js\nconst target = { a: 1 }\nObject.assign(target, { b: 2 })      \u002F\u002F mutates target -> { a: 1, b: 2 }\nconst fresh = { ...target, c: 3 }    \u002F\u002F new object, target untouched\n```\n\nSubtler difference: `Object.assign` **invokes setters** on the target, while\nspread defines plain data properties on a fresh object. Pitfall: passing a real\nobject as `Object.assign`'s first arg unintentionally mutates it — pass `{}`\nfirst (`Object.assign({}, a, b)`) for a non-mutating merge.\n",{"id":2457,"difficulty":161,"q":2458,"a":2459},"spread-with-getters","What happens to getters when you spread an object?","Spread **invokes** each getter and copies its returned value as a plain data\nproperty — the getter itself is not carried over. The copy holds a static\nsnapshot, not a live accessor.\n\n```js\nconst obj = { _n: 1, get n() { return this._n } }\nconst copy = { ...obj }\nobj._n = 99\nconsole.log(copy.n)                  \u002F\u002F 1  frozen snapshot, getter gone\nconsole.log(Object.getOwnPropertyDescriptor(copy, 'n').get)  \u002F\u002F undefined\n```\n\nTo preserve accessors you need `Object.getOwnPropertyDescriptors` +\n`Object.defineProperties`. Pitfall: spreading objects with getters silently\nflattens computed\u002Flazy properties into stale values.\n",{"id":1578,"difficulty":96,"q":2461,"a":2462},"What are rest parameters in a function?","A **rest parameter** (`...args`) collects all remaining arguments into a real\narray. It's the modern, array-native replacement for the `arguments` object.\n\n```js\nfunction sum(...nums) {\n  return nums.reduce((t, n) => t + n, 0)\n}\nsum(1, 2, 3)                         \u002F\u002F 6 — nums is [1, 2, 3]\n```\n\nUnlike `arguments`, `nums` is a genuine `Array` with `map`\u002F`reduce`\u002Fetc., and it\nworks in arrow functions. Pitfall: the rest parameter must be **last** —\n`function f(...a, b)` is a syntax error.\n",{"id":2464,"difficulty":88,"q":2465,"a":2466},"rest-vs-arguments","Why prefer rest parameters over the arguments object?","`arguments` is an **array-like** object — no array methods, and it doesn't exist\nin arrow functions. Rest parameters give a **real array** and work everywhere.\n\n```js\nfunction oldWay() {\n  const args = Array.prototype.slice.call(arguments)  \u002F\u002F awkward conversion\n  return args.map(x => x * 2)\n}\nconst newWay = (...args) => args.map(x => x * 2)       \u002F\u002F clean, works in arrows\n```\n\nRest also makes the signature self-documenting and can capture just the tail\nafter named params. Pitfall: `arguments` reflects all passed args ignoring\nparameter names, which surprises people refactoring to rest.\n",{"id":2468,"difficulty":88,"q":2469,"a":2470},"named-plus-rest-params","How do you combine named parameters with a rest parameter?","List the fixed parameters first, then `...rest` last to gather everything\nbeyond them. The named params consume the leading arguments; the rest collects\nthe tail.\n\n```js\nfunction log(level, ...messages) {\n  console.log(`[${level}]`, messages.join(' '))\n}\nlog('INFO', 'server', 'started')     \u002F\u002F level='INFO', messages=['server','started']\n```\n\n`rest` is empty (`[]`) if no extra arguments are passed — never `undefined`.\nPitfall: rest captures everything after the named params, so you can't place a\nrequired parameter after it.\n",{"id":2472,"difficulty":88,"q":2473,"a":2474},"spread-call-arguments","How do you pass an array as individual function arguments?","Use spread at the **call site**: `fn(...arr)` expands the array elements into\npositional arguments. This replaces the older `fn.apply(null, arr)`.\n\n```js\nconst nums = [3, 1, 4, 1, 5]\nMath.max(...nums)                    \u002F\u002F 5 — same as Math.max(3,1,4,1,5)\n\u002F\u002F Math.max(nums)                    \u002F\u002F NaN — array isn't a number\n```\n\nYou can mix spread with literals: `fn(0, ...nums, 9)`. Pitfall: spreading a very\nlarge array can exceed the engine's argument-count limit and throw `RangeError`.\n",{"id":2476,"difficulty":96,"q":2477,"a":2478},"swap-variables","How do you swap two variables without a temp variable?","Array destructuring lets you assign both sides simultaneously: the right side is\nevaluated into a temporary array, then unpacked back into the variables.\n\n```js\nlet a = 1, b = 2\n;[a, b] = [b, a]                     \u002F\u002F a=2, b=1, no temp needed\n```\n\nThe leading semicolon guards against the previous line being interpreted as a\nfunction call on `[`. Pitfall: forgetting that semicolon when the prior line has\nno `;` causes `2[a, b]` ASI bugs — a classic gotcha.\n",{"id":2480,"difficulty":88,"q":2481,"a":2482},"destructuring-return-values","How does destructuring help with functions that return objects?","A function can return one object and the caller destructures the fields it cares\nabout — order-independent, self-documenting, and easy to extend without breaking\ncallers.\n\n```js\nfunction parse(input) {\n  return { ok: true, value: input.trim(), length: input.length }\n}\nconst { value, ok } = parse('  hi ') \u002F\u002F pick fields by name, any order\n```\n\nAdding a new field to the returned object never breaks existing callers (unlike\nadding a positional array element). Pitfall: if the function can return `null`\n(e.g. a \"not found\" case), destructuring it throws — guard with `?? {}`.\n",{"id":2484,"difficulty":161,"q":2485,"a":2486},"deep-default-in-destructuring","How do nested destructuring and defaults interact when an intermediate is missing?","Each level of a nested pattern can carry its own default. A default on an\n**intermediate** object protects against that object being `undefined` before you\ndescend into it.\n\n```js\nfunction render({ theme: { color = 'black' } = {} } = {}) {\n  return color\n}\nrender()                             \u002F\u002F 'black' — every level defaulted\nrender({ theme: null })              \u002F\u002F TypeError — null isn't undefined, can't destructure\n```\n\nDefaults fire on `undefined` only, so a `null` intermediate still throws. Pitfall:\ncallers passing explicit `null` for a sub-object bypass your `= {}` guard — defend\nwith `?? {}` if `null` is possible.\n",{"id":2488,"difficulty":88,"q":2489,"a":2490},"spread-vs-rest-difference","What is the difference between spread and rest, since both use the ... syntax?","They are mirror images. **Rest collects** multiple items into one\narray\u002Fobject (appears in a parameter list or destructuring pattern). **Spread\nexpands** one iterable\u002Fobject into multiple items (appears in a call, array, or\nobject literal).\n\n```js\nconst [first, ...rest] = [1, 2, 3]   \u002F\u002F rest: collects -> rest = [2, 3]\nconst merged = [first, ...rest]      \u002F\u002F spread: expands -> [1, 2, 3]\n```\n\nRule of thumb: on the **left of `=`** or in **params** it's rest (gathering); on\nthe **right** or inside a literal\u002Fcall it's spread (scattering). Pitfall: same\n`...` token, opposite directions — context decides which.\n",{"id":281,"difficulty":88,"q":2492,"a":2493},"Can spread be used on things other than arrays?","In an **array literal** or function call, spread works on any **iterable** —\nstrings, `Set`, `Map`, `arguments`, generators. In an **object literal**, spread\nworks on any object's own enumerable properties.\n\n```js\n[...'abc']                           \u002F\u002F ['a', 'b', 'c']  string is iterable\n[...new Set([1, 1, 2])]              \u002F\u002F [1, 2]  dedupe trick\n{ ...{ a: 1 } }                      \u002F\u002F { a: 1 }  object spread\n\u002F\u002F [...{ a: 1 }]                     \u002F\u002F TypeError — plain object isn't iterable\n```\n\nPitfall: object spread and array spread are different mechanisms — a plain object\nis **not** iterable, so `[...obj]` throws even though `{ ...obj }` works.\n",{"id":2495,"difficulty":88,"q":2496,"a":2497},"destructuring-skip-and-rename","How can you destructure and immediately rename a property to avoid a name clash?","Renaming during destructuring sidesteps collisions with existing variables or\nreserved-ish names, and lets you give local, meaningful names.\n\n```js\nconst a = 1\nconst data = { a: 99, default: 'x' }\nconst { a: itemId, default: fallback } = data\nconsole.log(itemId, fallback)        \u002F\u002F 99 'x'  no clash with outer `a`\n```\n\nRenaming also lets you read keys that aren't valid identifiers (like `default`)\ninto usable names. Pitfall: forgetting to rename when a key shadows an in-scope\n`const` causes a redeclaration error.\n",{"id":2499,"difficulty":161,"q":2500,"a":2501},"array-of-objects-destructuring","How do you destructure objects inside an array in one pattern?","Combine array and object patterns: the array pattern picks positions, and each\nelement can itself be an object pattern that picks fields.\n\n```js\nconst users = [{ name: 'Ada' }, { name: 'Bob' }]\nconst [{ name: first }, { name: second }] = users\nconsole.log(first, second)           \u002F\u002F 'Ada' 'Bob'\n```\n\nYou can default a missing element to `{}` to avoid throwing: `[{ name } = {}] =\nusers`. Pitfall: if the array is shorter than the pattern, a missing element is\n`undefined` and destructuring into it throws unless you provide an element\ndefault.\n",{"id":2503,"difficulty":88,"q":2504,"a":2505},"spread-immutable-update","How does spread enable immutable state updates?","Spread the old state and override the changed fields in a new object, leaving the\noriginal untouched — the foundation of immutable updates in Redux, React, etc.\n\n```js\nconst state = { count: 0, user: 'Ada' }\nconst next = { ...state, count: state.count + 1 }\nconsole.log(state.count, next.count) \u002F\u002F 0 1  original preserved\n```\n\nThis makes change detection cheap (reference comparison) and supports\ntime-travel\u002Fundo. Pitfall: it's shallow — updating a **nested** slice requires\nspreading each level (`{ ...state, user: { ...state.user, ... } }`), or nested\nmutations leak into the old state.\n",{"id":2507,"difficulty":161,"q":2508,"a":2509},"default-from-other-param","Can a destructured default reference an earlier-destructured value?","Yes. Defaults are evaluated left to right, so a later field's default can use a\nvalue bound earlier in the same pattern.\n\n```js\nfunction area({ width, height = width } = {}) {\n  return width * height\n}\narea({ width: 5 })                   \u002F\u002F 25 — height defaults to width\n```\n\nThe binding must already be in scope (declared earlier in the pattern). Pitfall:\nreferencing a field declared **after** it throws a temporal-dead-zone\n`ReferenceError` — `{ a = b, b }` fails because `b` isn't initialized yet when\n`a`'s default runs.\n",{"id":2511,"difficulty":88,"q":2512,"a":2513},"spread-null-undefined","What happens when you spread null or undefined?","In an **object** literal, spreading `null` or `undefined` is silently ignored —\nno properties added, no error. In an **array** literal or call, spreading them\n**throws** because they aren't iterable.\n\n```js\nconst o = { ...null, ...undefined, a: 1 }  \u002F\u002F { a: 1 } — ignored safely\n\u002F\u002F const arr = [...null]                    \u002F\u002F TypeError: null is not iterable\n```\n\nThis asymmetry is handy: `{ ...(cond && extra) }` conditionally merges (since\n`false`\u002F`null` spread to nothing). Pitfall: the same `cond && extra` trick in an\n**array** spread throws when the condition is falsy.\n",{"id":2515,"difficulty":88,"q":2516,"a":2517},"rest-shallow-copy","Is the rest object from destructuring a deep or shallow copy?","**Shallow.** The rest pattern builds a new object whose nested values are still\nshared references with the source — only the top-level structure is new.\n\n```js\nconst src = { id: 1, meta: { x: 1 } }\nconst { id, ...rest } = src\nrest.meta.x = 99\nconsole.log(src.meta.x)              \u002F\u002F 99  shared nested reference mutated\n```\n\nSame shallow semantics as object spread (they use the same copy mechanism).\nPitfall: treating the rest object as fully isolated and mutating its nested\nmembers corrupts the original.\n",{"description":86},"JavaScript destructuring, spread and rest interview questions — object destructuring with renaming and defaults, nested and computed keys, object spread for copying and merging, rest parameters, and the shallow-copy gotcha.","javascript\u002Fmodern\u002Fdestructuring-spread-rest","Destructuring, Spread & Rest","j-ktPh8WpFhFjct2cigvLtRd0mYHyPvKzyn8tht5YrQ",{"id":2524,"title":2525,"body":2526,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":2530,"navigation":91,"order":29,"path":2531,"questions":2532,"related":224,"seo":2652,"seoDescription":2653,"stem":2654,"subtopic":2655,"topic":73,"topicSlug":75,"updated":228,"__hash__":2656},"qa\u002Fjavascript\u002Fmodern\u002Foptional-chaining-nullish.md","Optional Chaining Nullish",{"type":83,"value":2527,"toc":2528},[],{"title":86,"searchDepth":29,"depth":29,"links":2529},[],{},"\u002Fjavascript\u002Fmodern\u002Foptional-chaining-nullish",[2533,2537,2541,2545,2549,2553,2556,2560,2564,2568,2572,2576,2580,2584,2588,2592,2596,2600,2604,2608,2612,2616,2620,2624,2628,2632,2636,2640,2644,2648],{"id":2534,"difficulty":96,"q":2535,"a":2536},"what-is-optional-chaining","What is optional chaining?","**Optional chaining** (`?.`) accesses a nested property only if the value to its\nleft is **not `null` or `undefined`**; otherwise the whole expression\nshort-circuits and returns `undefined` instead of throwing.\n\n```js\nconst user = { profile: { name: 'Ada' } }\nconsole.log(user.profile?.name)      \u002F\u002F 'Ada'\nconsole.log(user.account?.balance)   \u002F\u002F undefined  no throw\n\u002F\u002F console.log(user.account.balance) \u002F\u002F TypeError: Cannot read 'balance' of undefined\n```\n\nIt replaces long `a && a.b && a.b.c` guards. Pitfall: it guards against `null`\u002F\n`undefined` only — it does **not** protect against other errors like calling a\nnon-function.\n",{"id":2538,"difficulty":96,"q":2539,"a":2540},"optional-chaining-properties","How does ?. work on nested property access?","`a?.b` evaluates `a`; if it's `null`\u002F`undefined` it returns `undefined`,\notherwise it accesses `b`. Chaining several `?.` guards each link in the path.\n\n```js\nconst data = { a: { b: null } }\nconsole.log(data?.a?.b?.c)           \u002F\u002F undefined  stops safely at b being null\n```\n\nImportantly, `?.` only checks the value **immediately to its left**. Pitfall:\n`data.a?.b.c` guards `a` but **not** `b` — if `b` is `null`, accessing `.c`\nstill throws. Put `?.` at every uncertain link.\n",{"id":2542,"difficulty":88,"q":2543,"a":2544},"optional-chaining-methods","How do you optionally call a method that might not exist?","Use `obj.method?.()`. If `method` is `null` or `undefined`, the call is skipped\nand the expression yields `undefined`; otherwise the method runs normally.\n\n```js\nconst api = { log: () => 'logged' }\nconsole.log(api.log?.())             \u002F\u002F 'logged'\nconsole.log(api.track?.())           \u002F\u002F undefined  no track method, no throw\n```\n\nHandy for optional callbacks: `onChange?.(value)`. Pitfall: if `method` exists\nbut is **not a function** (e.g. a number), `?.()` still throws `TypeError: not a\nfunction` — `?.` only guards `null`\u002F`undefined`, not wrong types.\n",{"id":2546,"difficulty":88,"q":2547,"a":2548},"optional-chaining-arrays","How does optional chaining work with array\u002Fdynamic access?","Use `arr?.[index]`. The `?.` before the bracket guards the array itself being\n`null`\u002F`undefined` before the element is read.\n\n```js\nconst result = { items: ['a', 'b'] }\nconsole.log(result.items?.[0])       \u002F\u002F 'a'\nconsole.log(result.tags?.[0])        \u002F\u002F undefined  no tags array, no throw\n```\n\nSame applies to computed keys: `obj?.[key]`. Pitfall: `arr?.[0]` guards `arr`,\nnot the element — if `arr` is `[]`, `arr?.[0]` is `undefined` (fine), but\n`arr?.[0].name` throws because element `0` is `undefined`.\n",{"id":2550,"difficulty":88,"q":2551,"a":2552},"short-circuiting","What does short-circuiting mean in optional chaining?","When `?.` hits a `null`\u002F`undefined`, it **stops evaluating the rest of the\nchain** and returns `undefined` immediately — nothing to the right runs,\nincluding function calls.\n\n```js\nlet calls = 0\nconst obj = null\nconst r = obj?.method(calls++)       \u002F\u002F undefined\nconsole.log(calls)                   \u002F\u002F 0  method() and calls++ never ran\n```\n\nThe entire chain after the short-circuit is skipped, side effects included.\nPitfall: people assume arguments still evaluate — they don't, so relying on a\nside effect inside a short-circuited call is a silent bug.\n",{"id":2182,"difficulty":96,"q":2554,"a":2555},"What is the nullish coalescing operator ??","`a ?? b` returns `a` unless it is **`null` or `undefined`**, in which case it\nreturns `b`. It provides a default only for \"no value\", not for any falsy value.\n\n```js\nconst port = userPort ?? 3000        \u002F\u002F use userPort unless it's null\u002Fundefined\nconsole.log(0 ?? 5)                  \u002F\u002F 0  0 is a real value, kept\nconsole.log(null ?? 5)               \u002F\u002F 5  null -> fallback\n```\n\nIt treats `0`, `''`, `false`, and `NaN` as legitimate values. Pitfall: don't\nreach for `??` when you actually want to reject *all* falsy values — that's `||`.\n",{"id":2557,"difficulty":88,"q":2558,"a":2559},"nullish-vs-or","What is the difference between ?? and ||?","`||` falls back on **any falsy** value (`0`, `''`, `false`, `NaN`, `null`,\n`undefined`). `??` falls back only on **`null`\u002F`undefined`**. The difference\nmatters whenever a falsy value is valid.\n\n```js\nconst count = 0\nconsole.log(count || 10)             \u002F\u002F 10  treats valid 0 as \"missing\"\nconsole.log(count ?? 10)             \u002F\u002F 0   keeps the real 0\nconsole.log('' || 'default')         \u002F\u002F 'default'  empty string lost\nconsole.log('' ?? 'default')         \u002F\u002F ''  empty string kept\n```\n\nUse `??` for defaults of numbers\u002Fstrings\u002Fbooleans. Pitfall: blindly migrating\nevery `||` to `??` (or vice-versa) changes behavior for zero\u002Fempty inputs — a\ncommon subtle regression.\n",{"id":2561,"difficulty":88,"q":2562,"a":2563},"when-to-use-or","When is || still the right choice over ???","Use `||` when you genuinely want **any falsy value** to trigger the fallback —\ne.g. treating empty string, `0`, or `false` the same as \"absent.\"\n\n```js\nconst name = input.name || 'Anonymous'   \u002F\u002F '' should also become Anonymous\nconst items = response.list || []        \u002F\u002F falsy\u002Fempty -> safe default array\n```\n\nHere an empty string genuinely means \"no name,\" so `||` is correct and `??`\nwould let `''` through. Pitfall: the choice is semantic — ask \"is a falsy value a\nlegitimate value here?\" If yes use `??`; if no, `||` is fine.\n",{"id":2565,"difficulty":88,"q":2566,"a":2567},"logical-assignment-nullish","What does the ??= operator do?","`a ??= b` assigns `b` to `a` **only if `a` is currently `null` or `undefined`**.\nIt's shorthand for `a = a ?? b`, but with a key twist: it assigns only when\nneeded.\n\n```js\nconst config = { timeout: 0 }\nconfig.timeout ??= 1000              \u002F\u002F stays 0  (0 isn't nullish)\nconfig.retries ??= 3                 \u002F\u002F becomes 3  (was undefined)\nconsole.log(config)                  \u002F\u002F { timeout: 0, retries: 3 }\n```\n\nIt only writes when the left side is nullish, so existing valid values (even\nfalsy ones) survive. Pitfall: confusing it with `||=`, which would overwrite the\n`0`.\n",{"id":2569,"difficulty":88,"q":2570,"a":2571},"logical-assignment-or","What does ||= do and how does it differ from ??=?","`a ||= b` assigns `b` when `a` is **falsy** (`a = a || b`); `a ??= b` assigns\nonly when `a` is **nullish**. The split mirrors the `||` vs `??` distinction.\n\n```js\nlet x = 0\nx ||= 5                              \u002F\u002F x = 5  overwrote valid 0\nlet y = 0\ny ??= 5                              \u002F\u002F y = 0  kept valid 0\n```\n\nBoth **short-circuit**: if no assignment is needed, the right side never\nevaluates (no side effects, no setter triggered). Pitfall: using `||=` to set a\ndefault on a numeric\u002Fboolean field clobbers legitimate `0`\u002F`false`.\n",{"id":2573,"difficulty":88,"q":2574,"a":2575},"logical-assignment-and","What does the &&= operator do?","`a &&= b` assigns `b` to `a` **only if `a` is truthy** (`a = a && b`). It's used\nto update a value only when it already exists.\n\n```js\nlet user = { name: 'Ada' }\nuser.name &&= user.name.toUpperCase()\nconsole.log(user.name)               \u002F\u002F 'ADA'  updated because it was truthy\nlet empty = null\nempty &&= 'x'                        \u002F\u002F stays null  falsy, left alone\n```\n\nLike the others it short-circuits — `b` only evaluates when `a` is truthy.\nPitfall: it's the least common of the three; people often reach for an `if` when\n`&&=` would read more cleanly (or vice versa where `if` is clearer).\n",{"id":2577,"difficulty":88,"q":2578,"a":2579},"combining-optional-and-nullish","How do you combine ?. with ?? for a safe default?","This is the canonical pair: `?.` safely walks a possibly-missing path and yields\n`undefined`, then `??` supplies a default for that `undefined`.\n\n```js\nconst user = { settings: null }\nconst theme = user?.settings?.theme ?? 'light'\nconsole.log(theme)                   \u002F\u002F 'light'  safe walk + default\n```\n\n`?.` handles the \"path might not exist,\" `??` handles the \"so use a fallback.\"\nPitfall: using `||` instead of `??` here would also override a legitimate\n`theme` of `''` or `0`, which `??` correctly preserves.\n",{"id":2581,"difficulty":161,"q":2582,"a":2583},"precedence-with-nullish","Why must you parenthesize ?? when mixing it with || or &&?","JavaScript **forbids** combining `??` with `||` or `&&` without parentheses — it's\na **syntax error** by design, because the intended precedence is ambiguous to\nreaders.\n\n```js\n\u002F\u002F const x = a || b ?? c             \u002F\u002F SyntaxError\nconst x = (a || b) ?? c              \u002F\u002F explicit grouping required\nconst y = a || (b ?? c)              \u002F\u002F the other grouping\n```\n\nThe language forces you to disambiguate rather than guessing. Pitfall: this is a\ncompile-time error, not a runtime one — copying a clever one-liner from `&&`\u002F`||`\nland into a `??` expression won't even parse.\n",{"id":2585,"difficulty":161,"q":2586,"a":2587},"optional-chaining-not-assignment","Can you use optional chaining on the left side of an assignment?","No. `?.` is only valid for **reading** (and deleting). Using it as an assignment\ntarget is a **syntax error** — you can't conditionally write through it.\n\n```js\nconst obj = { a: {} }\n\u002F\u002F obj?.a?.b = 5                     \u002F\u002F SyntaxError — invalid assignment target\nif (obj?.a) obj.a.b = 5             \u002F\u002F guard, then assign normally\n```\n\n`delete obj?.a.b` is allowed (short-circuits to a no-op if `obj` is nullish), but\nassignment is not. Pitfall: people expect symmetric read\u002Fwrite support and are\nsurprised the parser rejects the assignment form outright.\n",{"id":2589,"difficulty":161,"q":2590,"a":2591},"optional-chaining-overuse","What is the danger of over-using optional chaining?","Sprinkling `?.` everywhere **hides real bugs**. If a value should never be\n`null`, guarding it with `?.` silently swallows the case where it unexpectedly is,\nturning a loud crash into a quiet `undefined` that surfaces far away.\n\n```js\n\u002F\u002F a required user that's accidentally null:\nconst name = user?.profile?.name    \u002F\u002F becomes undefined, no signal something broke\nconst name2 = user.profile.name     \u002F\u002F throws loudly at the actual fault line\n```\n\nUse `?.` only where absence is **legitimate and expected**, not as a blanket\ncrash-suppressor. Pitfall: defensive `?.` everywhere defers the error to a\nconfusing downstream location, making bugs far harder to trace.\n",{"id":2593,"difficulty":161,"q":2594,"a":2595},"nullish-default-vs-destructuring-default","How does ?? differ from a destructuring default?","Both default on `undefined`, but a **destructuring default** does **not** trigger\non `null`, whereas `??` does. So they diverge whenever a value is explicitly\n`null`.\n\n```js\nconst { x = 1 } = { x: null }\nconsole.log(x)                       \u002F\u002F null  \u003C- destructuring default ignores null\nconst y = ({ x: null }).x ?? 1\nconsole.log(y)                       \u002F\u002F 1     \u003C- ?? catches null too\n```\n\nUse a destructuring default for \"missing key,\" and `??` (or both) when `null` is\nalso a \"use the fallback\" signal. Pitfall: assuming `{ x = d }` and `x ?? d`\nbehave identically — they differ precisely on `null`.\n",{"id":2597,"difficulty":88,"q":2598,"a":2599},"optional-call-on-array-method","How do you safely call a method on a possibly-missing array?","Chain `?.` before the method call: `arr?.map(...)`. If `arr` is `null`\u002F\n`undefined`, the whole call short-circuits to `undefined`.\n\n```js\nconst data = {}\nconst upper = data.tags?.map(t => t.toUpperCase())\nconsole.log(upper)                   \u002F\u002F undefined  no throw on missing tags\nconst safe = data.tags?.map(t => t) ?? []  \u002F\u002F fall back to empty array\n```\n\nPair with `?? []` if downstream code expects an array. Pitfall: `data.tags?.map`\nreturning `undefined` will break a chained `.filter()` after it — guard the whole\nchain or supply the `?? []` fallback.\n",{"id":2601,"difficulty":88,"q":2602,"a":2603},"double-question-mark-with-function-call","Does the right-hand side of ?? always evaluate?","No — `??` **short-circuits**. The right operand evaluates **only** when the left\nis `null`\u002F`undefined`. So an expensive default or a function call on the right is\nskipped when the left has a value.\n\n```js\nlet computed = 0\nconst v = 'cached' ?? expensive()    \u002F\u002F expensive() never runs\nfunction expensive() { computed++; return 'x' }\nconsole.log(computed)                \u002F\u002F 0  skipped\n```\n\nThis makes `value ?? buildDefault()` cheap in the common case. Pitfall: relying\non the right side's side effects is a bug, since it may never execute.\n",{"id":2605,"difficulty":161,"q":2606,"a":2607},"chaining-after-optional-call","How does a ?. short-circuit affect the rest of a long chain?","Once any `?.` short-circuits, the **entire remaining chain** — further property\naccesses, calls, and index lookups — is skipped, and the whole expression is\n`undefined`. The short-circuit \"infects\" everything to its right.\n\n```js\nconst obj = { a: null }\nconsole.log(obj.a?.b.c.d())          \u002F\u002F undefined  b.c.d() all skipped\n```\n\nYou don't need `?.` on every link **after** the one that may be nullish — the\nfirst short-circuit covers the rest. Pitfall: but each *independent* uncertain\nlink still needs its own `?.`; the short-circuit only protects links **downstream**\nof where it fired.\n",{"id":2609,"difficulty":96,"q":2610,"a":2611},"nullish-with-numbers","Why is ?? recommended for numeric defaults?","Because `0` is a valid number but **falsy**, `||` would wrongly replace it.\n`??` only replaces `null`\u002F`undefined`, so a real `0` survives.\n\n```js\nconst volume = settings.volume ?? 100   \u002F\u002F volume of 0 stays 0\n\u002F\u002F const bad = settings.volume || 100   \u002F\u002F 0 becomes 100 — muted unmute!\n```\n\nSame reasoning applies to any field where `0`, `''`, or `false` are meaningful.\nPitfall: a \"default to 100\" written with `||` silently breaks the legitimate-zero\ncase — a classic slider\u002Fquantity bug.\n",{"id":2613,"difficulty":161,"q":2614,"a":2615},"optional-chaining-with-this","Does optional chaining preserve the this binding in a method call?","Yes. `obj?.method()` keeps `this` bound to `obj`, exactly like a normal method\ncall — the `?.` only adds the nullish guard, it doesn't change the call's\nreceiver.\n\n```js\nconst counter = {\n  n: 5,\n  get() { return this.n }\n}\nconsole.log(counter?.get())          \u002F\u002F 5  this is still counter\n```\n\nThe short-circuit happens before the call, so `this` is irrelevant when it fires.\nPitfall: extracting the method first (`const g = counter?.get; g()`) **loses**\n`this`, just like without `?.` — optional chaining doesn't bind methods.\n",{"id":2617,"difficulty":88,"q":2618,"a":2619},"nullish-chaining-multiple","How do you chain multiple ?? operators?","`a ?? b ?? c` returns the **first non-nullish** value left to right. It's a clean\nway to express a fallback priority list.\n\n```js\nconst value = userSetting ?? cookieSetting ?? defaultSetting ?? 'fallback'\nconsole.log(null ?? undefined ?? 0)  \u002F\u002F 0  first non-nullish wins (0 counts)\n```\n\nEach `??` short-circuits, so evaluation stops at the first real value. Pitfall:\nthis is valid (chaining `??` with `??` is fine), but mixing in a `||` mid-chain\nwithout parentheses is a syntax error.\n",{"id":2621,"difficulty":161,"q":2622,"a":2623},"optional-delete","Can you use optional chaining with the delete operator?","Yes — `delete obj?.prop` deletes the property if `obj` exists, and is a **no-op**\n(returning `true`) if `obj` is `null`\u002F`undefined`. It's one of the few non-read\ncontexts `?.` allows.\n\n```js\nconst obj = { a: 1 }\ndelete obj?.a                        \u002F\u002F deletes a\nconst nothing = null\ndelete nothing?.x                    \u002F\u002F no-op, no throw\n```\n\nAssignment is still forbidden, but deletion is permitted because it short-circuits\ncleanly. Pitfall: it's an uncommon form, so reviewers may not realize the delete\nis conditionally skipped when the object is nullish.\n",{"id":2625,"difficulty":88,"q":2626,"a":2627},"nullish-assignment-lazy","How is ??= useful for lazy initialization or caching?","Because `??=` only assigns (and only evaluates the right side) when the property is\nnullish, it's perfect for \"compute once and cache\" — subsequent calls skip the\nwork.\n\n```js\nconst cache = {}\nfunction get(key) {\n  return cache[key] ??= expensiveLookup(key)  \u002F\u002F computed once per key\n}\n```\n\nOn the first call `cache[key]` is `undefined`, so the lookup runs and stores;\nlater calls return the cached value without recomputing. Pitfall: if\n`expensiveLookup` can legitimately return `null`\u002F`undefined`, it's treated as\n\"not cached\" and re-runs every time.\n",{"id":2629,"difficulty":88,"q":2630,"a":2631},"optional-chaining-falsy-confusion","Does ?. return undefined or the actual value when the chain succeeds?","When the chain **succeeds**, `?.` returns the real value — it does **not** convert\nanything. It only injects `undefined` when it actually short-circuits on a\nnullish link.\n\n```js\nconst obj = { a: 0, b: false }\nconsole.log(obj?.a)                  \u002F\u002F 0      real value\nconsole.log(obj?.b)                  \u002F\u002F false  real value, not undefined\nconsole.log(obj?.missing)            \u002F\u002F undefined  (short-circuit)\n```\n\nSo a result of `undefined` could mean \"short-circuited\" **or** \"property is\ngenuinely `undefined`.\" Pitfall: you can't distinguish those two cases from the\nresult alone — use `in` or `hasOwnProperty` if the difference matters.\n",{"id":2633,"difficulty":88,"q":2634,"a":2635},"nullish-in-jsx-or-template","Why is ?? safer than || when rendering values in UI?","In templating\u002FJSX, falsy-but-valid values like `0` or `''` should render. `||`\nwould replace them with the fallback, hiding real data; `??` keeps them.\n\n```js\n\u002F\u002F showing a like count:\nconst display = post.likes ?? 'N\u002FA'  \u002F\u002F 0 renders as 0\n\u002F\u002F const bad = post.likes || 'N\u002FA'   \u002F\u002F 0 likes shows 'N\u002FA'\n```\n\nSame for displaying an empty search query or a `false` toggle label. Pitfall:\n`||` in a render path is a frequent source of \"why does zero show as N\u002FA?\" bug\nreports.\n",{"id":2637,"difficulty":88,"q":2638,"a":2639},"optional-chaining-performance","Does optional chaining have meaningful performance cost?","Negligibly. `?.` compiles to a simple `null`\u002F`undefined` check before each\naccess — a tiny conditional. It's far cheaper than the bugs and verbose guards it\nreplaces.\n\n```js\n\u002F\u002F these are essentially equivalent in cost:\nconst a = obj && obj.prop\nconst b = obj?.prop                  \u002F\u002F same check, cleaner\n```\n\nThe \"cost\" worth watching is **semantic**, not CPU — readability and bug-hiding.\nPitfall: don't avoid `?.` for imagined perf reasons; the real concern is using it\nwhere a value should never be nullish (see over-use).\n",{"id":2641,"difficulty":161,"q":2642,"a":2643},"combining-optional-call-and-nullish","How do you safely invoke an optional callback and provide a result default?","Combine `?.()` (skip the call if the function is absent) with `??` (default the\nresult if the call was skipped or returned nullish).\n\n```js\nfunction process(data, transform) {\n  return transform?.(data) ?? data   \u002F\u002F use transform if given, else raw data\n}\nprocess(5)                           \u002F\u002F 5  — no transform, falls back\nprocess(5, x => x * 2)               \u002F\u002F 10 — transform applied\n```\n\n`transform?.(data)` is `undefined` when no callback is passed, and `?? data`\nsupplies the fallback. Pitfall: if `transform` legitimately returns `0`\u002F`''`,\n`??` keeps it (good), but `|| data` would wrongly discard those.\n",{"id":2645,"difficulty":88,"q":2646,"a":2647},"nullish-coalescing-with-assignment-target","Why prefer config.x ??= default over config.x = config.x ?? default?","They're equivalent in result, but `??=` is shorter and, crucially,\n**short-circuits the assignment**: when `config.x` already has a value, no write\nhappens — avoiding spurious setter calls or proxy traps.\n\n```js\n\u002F\u002F verbose:\nconfig.x = config.x ?? compute()\n\u002F\u002F concise + skips the write when x exists:\nconfig.x ??= compute()               \u002F\u002F\n```\n\nFor plain objects the difference is cosmetic; for objects with setters or\nreactive frameworks it avoids unnecessary side effects. Pitfall: on a getter-only\n(read-only) property, `??=` still attempts the write when nullish and throws in\nstrict mode.\n",{"id":2649,"difficulty":161,"q":2650,"a":2651},"optional-chaining-with-bracket-call","How do you combine dynamic key access and optional method calls in one chain?","You can mix `?.[key]` and `?.()` freely in a single chain; each `?.` guards its\nown link, and the first nullish one short-circuits the rest.\n\n```js\nconst handlers = { onSave: () => 'saved' }\nconst name = 'onSave'\nconsole.log(handlers?.[name]?.())    \u002F\u002F 'saved'\nconsole.log(handlers?.['onDelete']?.())  \u002F\u002F undefined  missing handler, no throw\n```\n\nThis pattern safely dispatches to a dynamically-named handler that may not exist.\nPitfall: `handlers[name]?.()` (no `?.` before `[name]`) still throws if\n`handlers` itself is nullish — guard the root too.\n",{"description":86},"JavaScript optional chaining and nullish coalescing interview questions — the ?. operator on properties, methods, and calls, ?? vs ||, logical assignment operators ??= ||= &&=, short-circuiting, and precedence pitfalls.","javascript\u002Fmodern\u002Foptional-chaining-nullish","Optional Chaining & Nullish Coalescing","WX3Bq31uUWq16_jGkIHCQ3CHmeRYaov98DiBBBbqeLY",{"id":2658,"title":2659,"body":2660,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":2664,"navigation":91,"order":47,"path":2665,"questions":2666,"related":224,"seo":2782,"seoDescription":2783,"stem":2784,"subtopic":2659,"topic":73,"topicSlug":75,"updated":228,"__hash__":2785},"qa\u002Fjavascript\u002Fmodern\u002Fsymbols.md","Symbols",{"type":83,"value":2661,"toc":2662},[],{"title":86,"searchDepth":29,"depth":29,"links":2663},[],{},"\u002Fjavascript\u002Fmodern\u002Fsymbols",[2667,2671,2675,2679,2683,2687,2691,2695,2699,2703,2707,2711,2714,2718,2722,2726,2730,2734,2738,2742,2746,2750,2754,2758,2762,2766,2770,2774,2778],{"id":2668,"difficulty":96,"q":2669,"a":2670},"what-is-symbol","What is a Symbol?","A **Symbol** is a primitive type (added in ES6) whose every value is\n**guaranteed unique**. You create one by calling `Symbol()`.\n\n```js\nconst a = Symbol()\nconst b = Symbol()\na === b   \u002F\u002F false  always unique, even with no description\ntypeof a  \u002F\u002F 'symbol'\n```\n\nTheir main use is as collision-proof object property keys and as\n\"well-known\" hooks that customize language behavior.\n",{"id":2672,"difficulty":96,"q":2673,"a":2674},"symbol-description","What is the symbol description for?","The optional string passed to `Symbol('desc')` is a **debug label** only —\nit does **not** affect identity. Two symbols with the same description are\nstill different.\n\n```js\nconst s = Symbol('userId')\ns.description   \u002F\u002F 'userId'  read-only label\nSymbol('x') === Symbol('x')   \u002F\u002F false\n```\n\nUse it to make logs and `toString()` output readable; never rely on it for\nequality.\n",{"id":2676,"difficulty":96,"q":2677,"a":2678},"symbol-no-new","Why can't you call Symbol with new?","`Symbol` is **not a constructor** — symbols are primitives, not objects, so\n`new Symbol()` throws a TypeError.\n\n```js\nconst s = Symbol('ok')      \u002F\u002F\nconst bad = new Symbol()    \u002F\u002F TypeError: Symbol is not a constructor\n```\n\nThis deliberately prevents accidental Symbol *wrapper objects*. If you ever\nneed the wrapper, `Object(symbol)` does it, but you rarely should.\n",{"id":2680,"difficulty":88,"q":2681,"a":2682},"symbol-as-key","How do you use a Symbol as an object key?","Use **computed property** syntax (`[sym]`) in a literal, or bracket\nassignment. The key is then accessible only by holding that exact symbol.\n\n```js\nconst id = Symbol('id')\nconst user = { [id]: 123, name: 'Ada' }\nuser[id]    \u002F\u002F 123\nuser.id     \u002F\u002F undefined — 'id' string is a different key\n```\n\nBecause the symbol is unique, this key can never clash with any string key\nor another library's symbol.\n",{"id":2684,"difficulty":88,"q":2685,"a":2686},"symbol-collision-free","Why are symbols useful for avoiding property collisions?","When you attach metadata to objects you don't own (or that mix data from\nmany sources), a symbol key is guaranteed not to overwrite or be overwritten\nby anyone else's key.\n\n```js\nconst CACHE = Symbol('cache')\nfunction memoize(obj) { obj[CACHE] = compute() }  \u002F\u002F won't clash\n```\n\nA string key like `obj.cache` risks stomping a real property; the symbol\ncan't, because no other code holds that symbol.\n",{"id":2688,"difficulty":88,"q":2689,"a":2690},"symbol-not-enumerable","Are symbol-keyed properties enumerable?","Symbol keys are **skipped** by `for...in`, `Object.keys`, `Object.values`,\n`Object.entries`, and `JSON.stringify` — they're effectively hidden from\nordinary enumeration.\n\n```js\nconst s = Symbol('hidden')\nconst o = { [s]: 1, visible: 2 }\nObject.keys(o)       \u002F\u002F ['visible']  symbol omitted\nJSON.stringify(o)    \u002F\u002F '{\"visible\":2}'\n```\n\nThis makes symbols handy for \"internal\" properties that shouldn't leak into\nserialization or iteration.\n",{"id":2692,"difficulty":88,"q":2693,"a":2694},"getownpropertysymbols","How do you retrieve symbol keys from an object?","Use **`Object.getOwnPropertySymbols`**, or `Reflect.ownKeys` to get string\nand symbol keys together.\n\n```js\nconst s = Symbol('id')\nconst o = { [s]: 1, name: 'x' }\nObject.getOwnPropertySymbols(o)  \u002F\u002F [Symbol(id)]\nReflect.ownKeys(o)               \u002F\u002F ['name', Symbol(id)]\n```\n\nSo symbols are **not truly private** — code with a reference to the object\ncan still discover and read them.\n",{"id":2696,"difficulty":88,"q":2697,"a":2698},"symbol-for","What is Symbol.for and the global symbol registry?","**`Symbol.for(key)`** looks up (or creates) a symbol in a process-wide\n**global registry** by string key — so the *same* key always returns the\n*same* symbol, even across modules or realms.\n\n```js\nSymbol.for('app.id') === Symbol.for('app.id')   \u002F\u002F true  shared\nSymbol('app.id')     === Symbol('app.id')        \u002F\u002F false — local\n```\n\nUse `Symbol.for` when different parts of a system must agree on one symbol;\nuse plain `Symbol()` for guaranteed-unique local keys.\n",{"id":2700,"difficulty":88,"q":2701,"a":2702},"symbol-keyfor","What does Symbol.keyFor do?","`Symbol.keyFor(sym)` returns the registry **key string** for a symbol\ncreated via `Symbol.for`, or `undefined` for a non-registered symbol.\n\n```js\nconst g = Symbol.for('shared')\nSymbol.keyFor(g)            \u002F\u002F 'shared'\nSymbol.keyFor(Symbol('x')) \u002F\u002F undefined — not in registry\n```\n\nIt's the inverse of `Symbol.for` and the only way to recover the key of a\nregistered symbol.\n",{"id":2704,"difficulty":88,"q":2705,"a":2706},"well-known-symbols","What are well-known symbols?","They are built-in symbols exposed as static properties on `Symbol` (e.g.\n`Symbol.iterator`, `Symbol.toPrimitive`) that let you **hook into language\noperations** by defining specially-keyed methods on your objects.\n\n```js\nconst range = {\n  [Symbol.iterator]() { \u002F* ... *\u002F }   \u002F\u002F makes object iterable\n}\n```\n\nImplementing the right well-known symbol customizes how your object behaves\nin `for...of`, `instanceof`, type coercion, spreading, and more.\n",{"id":2708,"difficulty":88,"q":2709,"a":2710},"symbol-iterator","How does Symbol.iterator make an object iterable?","Defining a `[Symbol.iterator]()` method that returns an iterator lets your\nobject work with `for...of`, spread, and destructuring.\n\n```js\nconst nums = {\n  *[Symbol.iterator]() { yield 1; yield 2; yield 3 }\n}\n[...nums]   \u002F\u002F [1, 2, 3]\n```\n\nAll built-in iterables (Array, Map, Set, String) implement this symbol — it\nis *the* protocol that makes iteration extensible.\n",{"id":1768,"difficulty":161,"q":2712,"a":2713},"What is Symbol.asyncIterator?","It's the async counterpart of `Symbol.iterator` — defining\n`[Symbol.asyncIterator]()` makes an object usable with **`for await...of`**,\nwhere each `next()` returns a Promise.\n\n```js\nconst stream = {\n  async *[Symbol.asyncIterator]() { yield await fetchChunk() }\n}\nfor await (const chunk of stream) { \u002F* ... *\u002F }   \u002F\u002F\n```\n\nUsed for streams and paginated\u002Fasync data sources where values arrive over\ntime.\n",{"id":2715,"difficulty":161,"q":2716,"a":2717},"symbol-toprimitive","How does Symbol.toPrimitive customize coercion?","Defining `[Symbol.toPrimitive](hint)` lets an object control its conversion\nto a primitive. The `hint` is `'number'`, `'string'`, or `'default'`\ndepending on context.\n\n```js\nconst money = {\n  amount: 5,\n  [Symbol.toPrimitive](hint) {\n    return hint === 'string' ? `$${this.amount}` : this.amount\n  }\n}\n`${money}`   \u002F\u002F '$5'   (string hint)\nmoney * 2    \u002F\u002F 10     (number hint)\n```\n\nIt overrides the default `valueOf`\u002F`toString` dance with a single, precise\nhook.\n",{"id":2719,"difficulty":161,"q":2720,"a":2721},"symbol-tostringtag","What does Symbol.toStringTag control?","It customizes the tag shown by **`Object.prototype.toString`** — the\n`[object X]` label.\n\n```js\nclass Money {\n  get [Symbol.toStringTag]() { return 'Money' }\n}\nObject.prototype.toString.call(new Money())  \u002F\u002F '[object Money]'\n```\n\nBuilt-ins use it too (`[object Map]`, `[object Promise]`). It's mostly for\ndebugging and type-branding, not control flow.\n",{"id":2723,"difficulty":161,"q":2724,"a":2725},"symbol-hasinstance","How can Symbol.hasInstance customize instanceof?","Defining a static `[Symbol.hasInstance](value)` method overrides what\n`value instanceof Class` returns — letting you do duck-typing checks.\n\n```js\nclass Even {\n  static [Symbol.hasInstance](n) { return n % 2 === 0 }\n}\n4 instanceof Even    \u002F\u002F true\n3 instanceof Even    \u002F\u002F false\n```\n\nPowerful but surprising — override `instanceof` sparingly, since readers\nassume it checks the prototype chain.\n",{"id":2727,"difficulty":88,"q":2728,"a":2729},"private-fields-pattern","Are symbols a way to create private properties?","They provide **soft privacy**: symbol keys are hidden from enumeration and\n`JSON.stringify`, so they won't accidentally leak — but anyone with the\nsymbol (or via `Object.getOwnPropertySymbols`) can still access them.\n\n```js\nconst _secret = Symbol('secret')\nclass Vault { constructor() { this[_secret] = 42 } }\n```\n\nFor **hard** privacy use class `#private` fields, which are truly\ninaccessible from outside. Symbols are for collision-avoidance, not\nsecurity.\n",{"id":2731,"difficulty":88,"q":2732,"a":2733},"symbols-and-json","What happens to symbols in JSON.stringify?","Symbol-**keyed** properties are ignored entirely, and a symbol **value**\nbecomes `undefined` (so it's dropped from objects or turned to `null` in\narrays).\n\n```js\nJSON.stringify({ [Symbol('k')]: 1, a: 2 })  \u002F\u002F '{\"a\":2}'  symbol key gone\nJSON.stringify({ a: Symbol('v') })          \u002F\u002F '{}'       symbol value gone\nJSON.stringify([Symbol('v')])               \u002F\u002F '[null]'\n```\n\nSo symbols never survive serialization — keep that in mind for state you\nneed to persist.\n",{"id":2735,"difficulty":96,"q":2736,"a":2737},"symbol-typeof","What does typeof return for a symbol?","**`'symbol'`** — it's its own primitive type alongside string, number,\nboolean, bigint, undefined, and object.\n\n```js\ntypeof Symbol()        \u002F\u002F 'symbol'\ntypeof Symbol.iterator \u002F\u002F 'symbol'\n```\n\nThat distinct `typeof` makes symbols easy to detect, e.g. when guarding a\nfunction that should reject symbol keys.\n",{"id":2739,"difficulty":88,"q":2740,"a":2741},"symbol-to-string-error","Why does implicit string conversion of a symbol throw?","Symbols **don't auto-coerce** to strings to avoid silent bugs — implicit\nconversion (concatenation, template slots) throws a TypeError. You must\nconvert explicitly.\n\n```js\nconst s = Symbol('id')\n'' + s            \u002F\u002F TypeError\n`${s}`            \u002F\u002F TypeError\nString(s)         \u002F\u002F 'Symbol(id)'  explicit\ns.toString()      \u002F\u002F 'Symbol(id)'\n```\n\n`String(sym)` and `.toString()` are the safe, intentional conversions.\n",{"id":2743,"difficulty":161,"q":2744,"a":2745},"symbols-not-cloned","How do symbol keys behave with Object.assign and spread?","They **are** copied — `Object.assign` and object spread copy *enumerable\nown* properties including symbol keys (symbol keys are enumerable for\ncopying purposes even though they're skipped by `for...in`\u002F`Object.keys`).\n\n```js\nconst s = Symbol('id')\nconst src = { [s]: 1, a: 2 }\nconst copy = { ...src }\ncopy[s]   \u002F\u002F 1  symbol key copied\n```\n\nSo spreading does preserve symbol-keyed data — a useful subtlety when you\nassumed they'd be dropped.\n",{"id":2747,"difficulty":88,"q":2748,"a":2749},"symbols-as-constants","Why use symbols for enum-like constants?","Symbols make **unforgeable, collision-free** constants — each is unique, so\nyou can't accidentally match by an equal string literal.\n\n```js\nconst Status = { ACTIVE: Symbol('active'), DONE: Symbol('done') }\nif (task.status === Status.ACTIVE) { \u002F* ... *\u002F }\n```\n\nUnlike string enums, a stray `'active'` elsewhere won't equal\n`Status.ACTIVE`. The tradeoff: symbols don't serialize, so use string enums\nwhen values cross network\u002Fstorage boundaries.\n",{"id":2751,"difficulty":161,"q":2752,"a":2753},"symbol-registry-cross-realm","Why is Symbol.for useful across realms or iframes?","The global registry is shared by string key across **realms** (iframes,\nworker boundaries, modules), so `Symbol.for('x')` yields a matching symbol\neverywhere, whereas a plain `Symbol()` from one realm is unique to it.\n\n```js\n\u002F\u002F iframe A and iframe B both run:\nSymbol.for('app.token')   \u002F\u002F same symbol identity in both\n```\n\nIt's the mechanism for agreeing on a symbol without sharing the actual\nreference.\n",{"id":2755,"difficulty":96,"q":2756,"a":2757},"detect-symbol-support","How do you check if a value is a symbol?","Use `typeof value === 'symbol'`. Avoid `instanceof Symbol`, which is false\nfor primitive symbols.\n\n```js\nconst isSymbol = v => typeof v === 'symbol'\nisSymbol(Symbol())          \u002F\u002F true\nSymbol() instanceof Symbol  \u002F\u002F false primitive, not an instance\n```\n\nThe `typeof` check is the only reliable test for symbol primitives.\n",{"id":2759,"difficulty":161,"q":2760,"a":2761},"well-known-species","What does Symbol.species control?","`Symbol.species` lets a class specify which **constructor** built-in methods\nlike `map`\u002F`filter`\u002F`slice` use to create derived instances.\n\n```js\nclass MyArray extends Array {\n  static get [Symbol.species]() { return Array }  \u002F\u002F map returns Array\n}\nconst r = new MyArray(1, 2, 3).map(x => x)\nr instanceof MyArray   \u002F\u002F false — it's a plain Array\n```\n\nIt's an advanced hook for subclassing built-ins; most code never needs it,\nbut it explains some surprising subclass behaviors.\n",{"id":2763,"difficulty":88,"q":2764,"a":2765},"symbol-iterator-builtin","How do you access the built-in iterator of an array via its symbol?","Call the array's `[Symbol.iterator]()` to get its iterator directly — the\nsame one `for...of` uses.\n\n```js\nconst arr = ['a', 'b']\nconst it = arr[Symbol.iterator]()\nit.next()   \u002F\u002F { value: 'a', done: false }\nit.next()   \u002F\u002F { value: 'b', done: false }\n```\n\nUseful when you want manual control over iteration or to forward an\niterator to other consuming code.\n",{"id":2767,"difficulty":161,"q":2768,"a":2769},"symbols-memory","Do registered symbols cause memory concerns?","Symbols from **`Symbol.for`** live in the global registry for the lifetime\nof the realm and are **never garbage-collected**, since the registry holds\nthem. Plain `Symbol()` values are collectible like any primitive once\nunreferenced.\n\n```js\nSymbol.for('keeps.living')   \u002F\u002F retained globally\nlet s = Symbol('local'); s = null  \u002F\u002F eligible for GC\n```\n\nPrefer plain symbols unless you genuinely need cross-module sharing, to\navoid unbounded registry growth.\n",{"id":2771,"difficulty":88,"q":2772,"a":2773},"symbols-vs-private-fields","When choose symbols over class private fields?","Use **`#private` fields** for true encapsulation within a single class. Use\n**symbols** when you need a non-enumerable key that's shareable across\nmodules, attachable to objects you don't own, or used in mixins.\n\n```js\nclass A { #real = 1 }          \u002F\u002F hard-private, class-scoped\nconst META = Symbol('meta')    \u002F\u002F shareable, attach anywhere\nsomeExternalObj[META] = 'tag'  \u002F\u002F works on foreign objects\n```\n\nPrivacy -> `#`; collision-free extensibility -> symbols.\n",{"id":2775,"difficulty":161,"q":2776,"a":2777},"symbol-default-hint","What is the 'default' hint in Symbol.toPrimitive?","The `'default'` hint is passed for operations that don't clearly want a\nnumber or string — chiefly **`+`** and **`==`** comparisons. You decide\nwhat makes sense.\n\n```js\nconst temp = {\n  c: 20,\n  [Symbol.toPrimitive](hint) {\n    if (hint === 'number') return this.c\n    if (hint === 'string') return `${this.c}°C`\n    return `${this.c}°C`   \u002F\u002F 'default' -> treat like string here\n  }\n}\ntemp + ''   \u002F\u002F '20°C'  (default hint)\n```\n\nMost objects map `'default'` to the same behavior as `'number'` or\n`'string'` depending on intent.\n",{"id":2779,"difficulty":88,"q":2780,"a":2781},"symbols-best-practices","What are best practices for using symbols?","Use plain `Symbol()` for collision-free metadata keys; reserve `Symbol.for`\nfor genuinely shared cross-module symbols; don't treat symbols as a\nsecurity mechanism; and convert to string explicitly with `String(sym)`.\n\n```js\nconst TAG = Symbol('tag')        \u002F\u002F local, unique\nthirdPartyObj[TAG] = 'mine'      \u002F\u002F safe to attach\n```\n\nImplement well-known symbols (`iterator`, `toPrimitive`) when you want\nobjects to integrate with language features — that's where symbols add the\nmost value.\n",{"description":86},"JavaScript Symbol interview questions — unique primitives, the global registry, symbol keys hidden from enumeration, well-known symbols like Symbol.iterator and Symbol.toPrimitive, and metaprogramming use cases.","javascript\u002Fmodern\u002Fsymbols","1lhIA2OYk4Bowpjxzvv-jTPSUsW0Rn_D38uNmRtHFAw",{"id":2787,"title":2788,"body":2789,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":2793,"navigation":91,"order":38,"path":2794,"questions":2795,"related":224,"seo":2916,"seoDescription":2917,"stem":2918,"subtopic":2919,"topic":73,"topicSlug":75,"updated":228,"__hash__":2920},"qa\u002Fjavascript\u002Fmodern\u002Ftemplate-literals.md","Template Literals",{"type":83,"value":2790,"toc":2791},[],{"title":86,"searchDepth":29,"depth":29,"links":2792},[],{},"\u002Fjavascript\u002Fmodern\u002Ftemplate-literals",[2796,2800,2804,2808,2812,2816,2820,2824,2828,2832,2836,2840,2844,2848,2852,2856,2860,2864,2868,2872,2876,2880,2884,2888,2892,2896,2900,2904,2908,2912],{"id":2797,"difficulty":96,"q":2798,"a":2799},"template-literal-basics","What is a template literal?","A **template literal** is a string written with **backticks** (`` ` ``)\nthat supports interpolation and spans multiple lines.\n\n```js\nconst name = 'Ada'\nconst msg = `Hello, ${name}!`   \u002F\u002F \"Hello, Ada!\"\n```\n\nBackticks replace the need for string concatenation and make embedded\nvalues far more readable than `'Hello, ' + name + '!'`.\n",{"id":2801,"difficulty":96,"q":2802,"a":2803},"interpolation","How does ${} interpolation work?","Any expression inside **`${ }`** is evaluated and its result coerced to a\nstring, then spliced into place.\n\n```js\nconst a = 5, b = 3\n`Sum is ${a + b}`         \u002F\u002F \"Sum is 8\"\n`Upper: ${name.toUpperCase()}`  \u002F\u002F method calls allowed\n```\n\nIt's a full expression slot — arithmetic, calls, ternaries, even nested\ntemplate literals all work. It is **not** a statement slot, so `if`\u002F`for`\ncan't go there.\n",{"id":2805,"difficulty":96,"q":2806,"a":2807},"multiline-strings","How do template literals handle multiline strings?","Newlines inside backticks are **preserved literally** — no `\\n` or\nconcatenation needed.\n\n```js\nconst text = `Line 1\nLine 2`         \u002F\u002F contains a real newline\n```\n\nPitfall: indentation inside the literal becomes part of the string. Leading\nspaces on the second line are included, which can surprise you when the\ncode is nested deep in a function.\n",{"id":2809,"difficulty":88,"q":2810,"a":2811},"expression-embedding","What kinds of expressions can you embed?","Any valid JavaScript **expression**: arithmetic, function calls, ternaries,\nproperty access, even another template literal.\n\n```js\n`Status: ${active ? 'on' : 'off'}`\n`Total: ${items.reduce((s, i) => s + i.price, 0)}`   \u002F\u002F\n```\n\nKeep them simple, though — heavy logic inside `${}` hurts readability.\nCompute into a variable first when the expression gets complex.\n",{"id":2813,"difficulty":88,"q":2814,"a":2815},"nested-templates","Can you nest template literals?","Yes — a `${}` slot can contain another backtick string, which is useful for\nconditional fragments.\n\n```js\nconst html = `\u003Cul>${items.map(i => `\u003Cli>${i}\u003C\u002Fli>`).join('')}\u003C\u002Ful>`\n```\n\nIt works, but deeply nested templates become hard to read. For non-trivial\nmarkup, prefer a templating library or break the pieces into named\nvariables.\n",{"id":2817,"difficulty":88,"q":2818,"a":2819},"tagged-template-basics","What is a tagged template?","A **tagged template** calls a function with the literal's parts. The tag\nfunction receives the array of **string segments** first, then each\ninterpolated **value** as subsequent arguments.\n\n```js\nfunction tag(strings, ...values) {\n  return { strings, values }\n}\ntag`Hi ${name}, you are ${age}`\n\u002F\u002F strings: ['Hi ', ', you are ', ''], values: [name, age]\n```\n\nThe tag fully controls the output — it doesn't have to return a string at\nall. This powers libraries like styled-components and graphql-tag.\n",{"id":2821,"difficulty":88,"q":2822,"a":2823},"tagged-template-strings-values","Why does the strings array always have one more element than values?","Because the string segments **surround** the interpolations — there's\nalways a piece before the first `${}` and after the last one (possibly\nempty).\n\n```js\ntag`a${1}b${2}c`\n\u002F\u002F strings: ['a', 'b', 'c']  (3)\n\u002F\u002F values:  [1, 2]           (2)  strings.length === values.length + 1\n```\n\nTag functions rely on this invariant to interleave: zip\n`strings[i]` with `values[i]` and append the final `strings[n]`.\n",{"id":2825,"difficulty":88,"q":2826,"a":2827},"string-raw","What does String.raw do?","**`String.raw`** is a built-in tag that returns the string with escape\nsequences **uninterpreted** — backslashes stay literal.\n\n```js\nString.raw`C:\\new\\test`   \u002F\u002F 'C:\\\\new\\\\test' (backslashes kept)\n`C:\\new\\test`             \u002F\u002F 'C:' + newline + 'ew' + tab + 'est'\n```\n\nGreat for Windows paths, regex source, and LaTeX. The `strings.raw`\nproperty is how any custom tag accesses the un-escaped segments.\n",{"id":2829,"difficulty":161,"q":2830,"a":2831},"raw-property","What is the .raw property on the strings array?","Inside a tag, `strings` also carries a **`raw`** array holding the\nsegments **before** escape processing — so the tag can choose cooked or raw\ntext.\n\n```js\nfunction show(strings) {\n  return strings.raw[0]   \u002F\u002F raw, e.g. '\\\\n' stays as backslash-n\n}\nshow`\\n`   \u002F\u002F '\\\\n'  not an actual newline\n```\n\n`String.raw` is literally implemented by joining `strings.raw` with the\nvalues.\n",{"id":2833,"difficulty":88,"q":2834,"a":2835},"i18n-use-case","How are tagged templates used for internationalization?","A tag can rebuild the message from its parts, looking up a translated\ntemplate by the static `strings` segments and re-inserting the dynamic\nvalues.\n\n```js\nfunction i18n(strings, ...values) {\n  const key = strings.join('{}')          \u002F\u002F stable lookup key\n  const translated = dictionary[key] ?? key\n  return interpolate(translated, values)   \u002F\u002F locale-aware\n}\ni18n`Hello ${name}`\n```\n\nBecause the static parts are constant per call site, they make a reliable\ntranslation key.\n",{"id":2837,"difficulty":161,"q":2838,"a":2839},"html-escaping-tag","How can a tagged template prevent injection?","The tag escapes the **interpolated values** while leaving the static\n`strings` (trusted, author-written) untouched — exactly what raw template\nliterals fail to do.\n\n```js\nfunction safeHtml(strings, ...values) {\n  return strings.reduce((out, s, i) =>\n    out + s + (i \u003C values.length ? escapeHtml(values[i]) : ''), '')\n}\nsafeHtml`\u003Cp>${userInput}\u003C\u002Fp>`   \u002F\u002F userInput is escaped\n```\n\nThis is the secure pattern; plain `` `\u003Cp>${userInput}\u003C\u002Fp>` `` injects raw\nuser input.\n",{"id":2841,"difficulty":161,"q":2842,"a":2843},"injection-risk","What's the security pitfall of plain template literals?","They perform **no escaping** — interpolated values go in verbatim. Building\nHTML or SQL by interpolation invites XSS\u002FSQL injection.\n\n```js\nel.innerHTML = `\u003Cdiv>${userInput}\u003C\u002Fdiv>`   \u002F\u002F XSS if userInput has \u003Cscript>\ndb.query(`SELECT * FROM u WHERE id = ${id}`) \u002F\u002F SQL injection\n```\n\nUse a sanitizing tag for HTML, and **parameterized queries** for SQL —\nnever interpolate untrusted data into markup or queries directly.\n",{"id":2845,"difficulty":96,"q":2846,"a":2847},"concatenation-comparison","Why prefer template literals over string concatenation?","They're more readable, avoid `+` clutter and stray-space bugs, and handle\nmultiline naturally.\n\n```js\n'Hi ' + name + ', you have ' + n + ' items'   \u002F\u002F noisy\n`Hi ${name}, you have ${n} items`             \u002F\u002F clear\n```\n\nConcatenation also silently coerces with `+`, where a misplaced operand can\nproduce `NaN` or \"[object Object]\"; template slots make intent explicit.\n",{"id":2849,"difficulty":88,"q":2850,"a":2851},"coercion-in-template","How are non-string values coerced inside a template?","Each `${}` result is converted with the abstract ToString — objects call\n`toString()`, arrays join with commas, `null`\u002F`undefined` stringify\nliterally.\n\n```js\n`${[1, 2, 3]}`    \u002F\u002F '1,2,3'\n`${ {a: 1} }`     \u002F\u002F '[object Object]'  rarely what you want\n`${null}`         \u002F\u002F 'null'\n```\n\nFor objects you usually want `JSON.stringify(obj)` inside the slot rather\nthan relying on the default `[object Object]`.\n",{"id":2853,"difficulty":96,"q":2854,"a":2855},"escaping-backtick","How do you include a backtick or ${ literally?","Escape them with a backslash.\n\n```js\n`A backtick: \\``        \u002F\u002F \"A backtick: `\"\n`Not a slot: \\${x}`     \u002F\u002F \"Not a slot: ${x}\"  literal\n```\n\nWithout the backslash, `${x}` would be interpreted as interpolation. This\nmatters when generating template-literal source code or documentation.\n",{"id":2857,"difficulty":88,"q":2858,"a":2859},"css-in-js","How do tagged templates enable CSS-in-JS?","Libraries like styled-components expose a tag that turns the literal into a\nstyled component, injecting interpolated values as dynamic style props.\n\n```js\nconst Button = styled.button`\n  color: ${props => props.primary ? 'white' : 'black'};\n`   \u002F\u002F tag processes the CSS + functions\n```\n\nThe tag receives the CSS chunks and the prop-accessor functions, then\ngenerates real stylesheets at render time.\n",{"id":2861,"difficulty":88,"q":2862,"a":2863},"graphql-gql","Why does GraphQL use a gql tagged template?","The `gql` tag parses the query string into an **AST** at definition time,\ncatching syntax errors early and enabling tooling (highlighting, type\ngeneration) on the embedded query.\n\n```js\nconst QUERY = gql`\n  query { user { id name } }\n`   \u002F\u002F parsed, not just a string\n```\n\nIt also lets fragments be interpolated and composed via `${}` while keeping\na single parse step.\n",{"id":2865,"difficulty":161,"q":2866,"a":2867},"performance-static-strings","Are the strings arrays in tagged templates cached?","Yes — for a given tagged-template **call site**, the engine reuses the\n**same frozen `strings` array** across invocations. This lets tags memoize\nby identity.\n\n```js\nfunction tag(strings) { \u002F* strings is the same object each call *\u002F }\nfunction run() { return tag`hello` }\nrun() ; run()   \u002F\u002F both calls receive the identical strings reference\n```\n\nLibraries exploit this to cache parsed templates (e.g. compiled CSS or\nGraphQL) keyed on the `strings` object.\n",{"id":2869,"difficulty":88,"q":2870,"a":2871},"dedent-indentation","How do you handle unwanted indentation in multiline templates?","The literal preserves source indentation, so nested code leaks leading\nspaces. Use a **dedent** tag or post-process with a regex.\n\n```js\nconst sql = `\n  SELECT *\n  FROM users\n`   \u002F\u002F each line has leading spaces\n\nconst clean = sql.replace(\u002F^\\s+\u002Fgm, '')   \u002F\u002F strip leading whitespace\n```\n\nDedent helper tags are common in test fixtures and embedded SQL\u002FGraphQL to\nkeep output clean while keeping source readable.\n",{"id":2873,"difficulty":96,"q":2874,"a":2875},"ternary-in-slot","How do you add conditional content inside a template?","Use a **ternary** or short-circuit expression in the slot — statements\naren't allowed.\n\n```js\n`Cart${count !== 1 ? 's' : ''}`           \u002F\u002F pluralize\n`${error ? `Error: ${error}` : 'OK'}`     \u002F\u002F nested + conditional\n```\n\nFor anything beyond a simple ternary, compute the fragment in a variable\nfirst to keep the literal readable.\n",{"id":2877,"difficulty":88,"q":2878,"a":2879},"arrays-join-in-template","How do you render a list inside a template literal?","Map to strings and **`join`** — relying on default array coercion adds\ncommas you usually don't want.\n\n```js\n`\u003Cul>${items.map(i => `\u003Cli>${i}\u003C\u002Fli>`).join('')}\u003C\u002Ful>`   \u002F\u002F\n`\u003Cul>${items}\u003C\u002Ful>`   \u002F\u002F inserts commas between items\n```\n\nThe explicit `.join('')` (or `.join(', ')`) controls the separator instead\nof getting the implicit comma.\n",{"id":2881,"difficulty":88,"q":2882,"a":2883},"template-vs-format","Do template literals support format specifiers like printf?","No — there's no `%d`\u002F`%s` formatting. You format inside the slot with\nmethods or `Intl`.\n\n```js\n`Price: ${value.toFixed(2)}`                       \u002F\u002F 2 decimals\n`Date: ${new Intl.DateTimeFormat('en').format(d)}` \u002F\u002F locale format\n```\n\nFor padding\u002Fnumber formatting use `padStart`, `toLocaleString`, or `Intl.*`\nrather than expecting printf-style directives.\n",{"id":2885,"difficulty":96,"q":2886,"a":2887},"empty-interpolation","What happens with an empty or whitespace ${} slot?","`${}` with nothing is a **SyntaxError** — a slot must contain an\nexpression. Whitespace alone is also invalid.\n\n```js\n`${}`        \u002F\u002F SyntaxError\n`${ '' }`    \u002F\u002F an empty-string expression is fine\n`${ \u002F* x *\u002F undefined }`  \u002F\u002F valid, inserts 'undefined'\n```\n\nYou need a real expression; if you want nothing, interpolate an empty\nstring `''`.\n",{"id":2889,"difficulty":161,"q":2890,"a":2891},"tagged-non-string-return","Can a tagged template return something other than a string?","Yes — the tag's return value is whatever the function returns. It can be an\nobject, a component, a parsed AST, a function, anything.\n\n```js\nfunction obj(strings, ...values) {\n  return { template: strings, data: values }   \u002F\u002F returns an object\n}\nconst x = obj`a ${1}`   \u002F\u002F x is an object, not a string\n```\n\nThis flexibility is the whole point — tags are a DSL hook, not just string\nformatters.\n",{"id":2893,"difficulty":88,"q":2894,"a":2895},"line-continuation","How do you write a long single-line string without a literal newline?","End a line with a **backslash** to continue without inserting a newline.\n\n```js\nconst s = `This is one long \\\nlogical line`   \u002F\u002F no newline between 'long ' and 'logical'\n```\n\nBe careful: any spaces after the backslash break it. This is occasionally\nhandy, but joining string parts or using normal wrapping is usually\nclearer.\n",{"id":2897,"difficulty":88,"q":2898,"a":2899},"template-with-functions","Can you call a function and use its result in a slot?","Yes — slots are expressions, so calls (including IIFEs) are allowed and\ntheir return value is interpolated.\n\n```js\n`Now: ${getTime()}`\n`Result: ${(() => compute())()}`   \u002F\u002F IIFE result\n```\n\nSide effects run at interpolation time, in left-to-right order with the\nother slots — keep that in mind if a slot mutates state.\n",{"id":2901,"difficulty":88,"q":2902,"a":2903},"comparison-with-sprintf","When might you still want a formatting library instead of templates?","For locale-aware numbers\u002Fdates, complex pluralization (ICU MessageFormat),\nor printf-style alignment, dedicated libraries (`Intl`, `messageformat`) do\nwhat raw templates can't.\n\n```js\n\u002F\u002F pluralization rules vary by language — a template can't express them all\nmessageFormat.format({ count })   \u002F\u002F handles one\u002Ffew\u002Fmany per locale\n```\n\nTemplates excel at simple interpolation and embedded DSLs; reach for\nformatting libs when human-language or numeric formatting gets involved.\n",{"id":2905,"difficulty":88,"q":2906,"a":2907},"jsx-relation","Are template literals related to JSX?","No — JSX is a separate compile-time syntax transformed by Babel\u002FTypeScript,\nnot a runtime template literal. But tagged templates (`html\\`...\\``) are\nthe **JSX-free** alternative used by libraries like lit-html.\n\n```js\n\u002F\u002F lit-html: tagged template, no build step needed\nhtml`\u003Cdiv>${content}\u003C\u002Fdiv>`   \u002F\u002F runtime, parsed by the html tag\n```\n\nSo tagged templates give a \"JSX-like\" templating experience without a\ncompiler.\n",{"id":2909,"difficulty":161,"q":2910,"a":2911},"whitespace-control","How do you control whitespace between interpolations?","Whatever sits between `${}` slots in the source is kept exactly, so you\nmanage spacing by what you type — or strip it in a tag.\n\n```js\n`${a} ${b}`     \u002F\u002F single space between\n`${a}${b}`      \u002F\u002F no space\n`${a}\n${b}`           \u002F\u002F newline preserved between them\n```\n\nFor HTML where whitespace collapses anyway it rarely matters; for\nprecise output (CSV, fixed-width), a normalizing tag gives full control.\n",{"id":2913,"difficulty":96,"q":2914,"a":2915},"best-practices","What are best practices for template literals?","Keep `${}` expressions simple, never interpolate untrusted data into\nHTML\u002FSQL without escaping\u002Fparameters, use `String.raw` for paths\u002Fregex, and\nmind leaked indentation in multiline strings.\n\n```js\nconst label = `${count} ${count === 1 ? 'item' : 'items'}`  \u002F\u002F simple\nel.textContent = `Hello ${name}`   \u002F\u002F textContent, not innerHTML\n```\n\nPrefer `textContent` over `innerHTML`, and a sanitizing tag when raw markup\nis unavoidable.\n",{"description":86},"JavaScript template literal interview questions — interpolation, multiline strings, expression embedding, tagged templates, String.raw and security pitfalls around escaping.","javascript\u002Fmodern\u002Ftemplate-literals","Template Literals & Tagged Templates","omSaAPQVGjJbVBYUSbK9SnLVjjpYF_CcFJGLpbxUZSU",{"id":2922,"title":2923,"body":2924,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":2928,"navigation":91,"order":47,"path":2929,"questions":2930,"related":224,"seo":3031,"seoDescription":3032,"stem":3033,"subtopic":3034,"topic":46,"topicSlug":48,"updated":228,"__hash__":3035},"qa\u002Fjavascript\u002Fobjects\u002Fnew-constructors.md","New Constructors",{"type":83,"value":2925,"toc":2926},[],{"title":86,"searchDepth":29,"depth":29,"links":2927},[],{},"\u002Fjavascript\u002Fobjects\u002Fnew-constructors",[2931,2935,2939,2943,2947,2951,2955,2959,2963,2967,2971,2975,2979,2983,2987,2991,2995,2999,3003,3007,3011,3015,3019,3023,3027],{"id":2932,"difficulty":88,"q":2933,"a":2934},"what-does-new-do","What does the new operator do?","`new Fn(args)` performs four steps:\n\n1. Creates a fresh empty object.\n2. Sets that object's prototype to `Fn.prototype`.\n3. Calls `Fn` with `this` bound to the new object.\n4. Returns the new object — unless `Fn` explicitly returns its own object.\n\n```js\nfunction User(name) { this.name = name }\nconst u = new User('Ada')\n\u002F\u002F roughly:\n\u002F\u002F const u = Object.create(User.prototype)\n\u002F\u002F User.call(u, 'Ada')\n```\n\nThose four steps are the whole \"magic\" of `new`. Understanding them explains\n`this`, the prototype link, and the return-value rules below.\n",{"id":2936,"difficulty":96,"q":2937,"a":2938},"constructor-function","What is a constructor function?","A regular function intended to be called with `new` to create objects. By\nconvention its name is **capitalized**. Inside, `this` is the new instance.\n\n```js\nfunction Point(x, y) {\n  this.x = x\n  this.y = y\n}\nconst p = new Point(1, 2)   \u002F\u002F { x: 1, y: 2 }\n```\n\nThere's nothing special about the function itself — any function can be a\nconstructor. The capitalization is a signal to callers that it must be invoked\nwith `new`. Classes are the modern replacement.\n",{"id":2940,"difficulty":161,"q":2941,"a":2942},"forget-new","What happens if you forget new on a constructor function?","Without `new`, the function runs as a plain call: `this` is `undefined` (strict)\nor the global object (sloppy), so it doesn't create an instance — and in sloppy\nmode it leaks properties onto the global object.\n\n```js\nfunction User(name) { this.name = name }\nconst u = User('Ada')   \u002F\u002F no new\nu                       \u002F\u002F undefined (function returns nothing)\n\u002F\u002F sloppy mode: created a global `name`!\n```\n\nGuards: use a `class` (which throws if called without `new`), or check\n`new.target`\u002F`instanceof` and re-invoke with `new`. This bug is exactly why\nclasses enforce `new`.\n",{"id":2944,"difficulty":161,"q":2945,"a":2946},"return-from-constructor","What happens when a constructor returns a value?","If a constructor returns an **object**, that object replaces the newly created\n`this`. If it returns a **primitive** (or nothing), the primitive is ignored and\n`this` is returned as usual.\n\n```js\nfunction A() { this.x = 1; return { y: 2 } }\nnew A()   \u002F\u002F { y: 2 } — object return overrides `this`\n\nfunction B() { this.x = 1; return 42 }\nnew B()   \u002F\u002F { x: 1 } — primitive return ignored\n```\n\nThis \"return an object to override\" behavior enables some factory tricks but is\nusually a footgun — most constructors return nothing.\n",{"id":2948,"difficulty":161,"q":2949,"a":2950},"new-target","What is new.target?","A meta-property that is the constructor invoked with `new`, or `undefined` for a\nnormal call. It lets a function detect how it was called.\n\n```js\nfunction User(name) {\n  if (!new.target) throw new Error('User must be called with new')\n  this.name = name\n}\nUser('Ada')      \u002F\u002F throws\nnew User('Ada')  \u002F\u002F\n```\n\nIn a class hierarchy, `new.target` is the actual subclass being constructed —\nuseful for abstract base classes and for factory logic that varies by concrete\ntype.\n",{"id":2952,"difficulty":88,"q":2953,"a":2954},"new-and-prototype","How does new connect an instance to its prototype?","`new Fn()` sets the instance's prototype to `Fn.prototype`, so the instance\ninherits everything defined there.\n\n```js\nfunction Dog() {}\nDog.prototype.bark = () => 'woof'\nconst d = new Dog()\nObject.getPrototypeOf(d) === Dog.prototype  \u002F\u002F true\nd.bark()                                      \u002F\u002F 'woof' (inherited)\n```\n\nThat's why methods go on `Fn.prototype` — every `new` instance shares them via\nthe prototype link. Reassigning `Fn.prototype` after creating an instance\ndoesn't change that instance's prototype.\n",{"id":2956,"difficulty":88,"q":2957,"a":2958},"constructor-vs-factory","What is the difference between a constructor and a factory function?","- A **constructor** is used with `new`, relies on `this`, and links instances to\n  a shared prototype.\n- A **factory** is a normal function that **returns** an object (no `new`, no\n  `this`), often using closures for privacy and composition for behavior.\n\n```js\nfunction User(name) { this.name = name }       \u002F\u002F constructor -> new User()\nfunction createUser(name) { return { name } }   \u002F\u002F factory -> createUser()\n```\n\nFactories avoid `new`\u002F`this` pitfalls and offer closure-based privacy;\nconstructors\u002Fclasses share methods via the prototype (more memory-efficient for\nmany instances). Both are valid.\n",{"id":2960,"difficulty":88,"q":2961,"a":2962},"this-in-constructor","What is this inside a constructor?","When called with `new`, `this` is the brand-new instance being created, so\nassignments to `this.x` become the object's own properties.\n\n```js\nfunction Account(balance) {\n  this.balance = balance       \u002F\u002F own property of the new instance\n  this.deposit = function (n) { this.balance += n }\n}\n```\n\nCalled **without** `new`, `this` follows normal rules (undefined\u002Fglobal), which\nis the source of the \"forgot new\" bug. Inside a class constructor, `this` is the\ninstance (and is `undefined` until `super()` runs in a subclass).\n",{"id":2964,"difficulty":88,"q":2965,"a":2966},"constructor-property-instance","How do you find which constructor created an object?","Use `instance.constructor` (inherited from the prototype) or `instanceof`.\n\n```js\nfunction User() {}\nconst u = new User()\nu.constructor === User        \u002F\u002F true\nu.constructor.name            \u002F\u002F 'User'\nu instanceof User             \u002F\u002F true\n```\n\n`constructor` is informational and can be wrong if the prototype was replaced\nwithout restoring it. For reliable type checks, prefer `instanceof` (or\nduck-typing), not the `constructor` property.\n",{"id":2968,"difficulty":96,"q":2969,"a":2970},"built-in-constructors","What are the built-in constructors?","JavaScript provides constructors for its core types: `Object`, `Array`,\n`Function`, `Date`, `RegExp`, `Map`, `Set`, `Promise`, `Error`, and the wrapper\nconstructors `String`\u002F`Number`\u002F`Boolean`.\n\n```js\nnew Date()\nnew Map()\nnew Error('boom')\nnew Array(3)        \u002F\u002F [ \u003C3 empty items> ] — quirky\n```\n\nMost are used with `new`, though some (like `Array`, `Object`) also work without\nit. **Avoid** `new String\u002FNumber\u002FBoolean` — they create wrapper *objects* that\nbreak `===` and are always truthy.\n",{"id":2972,"difficulty":88,"q":2973,"a":2974},"array-constructor-pitfall","What is the pitfall of the Array constructor?","`new Array(n)` with a **single number** creates an empty array of length `n`\n(holes), not an array containing `n`. With multiple args it creates an array of\nthose elements.\n\n```js\nnew Array(3)        \u002F\u002F [ \u003C3 empty items> ] — length 3, no values\nnew Array(1, 2, 3)  \u002F\u002F [1, 2, 3]\nArray.of(3)         \u002F\u002F [3] — the unambiguous alternative\nArray.from({length: 3}, (_, i) => i)  \u002F\u002F [0, 1, 2]\n```\n\nThis inconsistency is why `Array.of` exists and why array literals `[]` are\npreferred. The \"empty items\" are holes, which behave oddly with iteration.\n",{"id":2976,"difficulty":88,"q":2977,"a":2978},"instanceof-check","How does instanceof relate to constructors?","`obj instanceof Ctor` is true when `Ctor.prototype` is in `obj`'s prototype\nchain — i.e. `obj` was (effectively) built by `Ctor` or a subclass.\n\n```js\nconst d = new Date()\nd instanceof Date    \u002F\u002F true\nd instanceof Object  \u002F\u002F true (Object.prototype is in the chain)\n```\n\nIt checks the prototype chain, not the literal constructor used, so it sees\ninheritance. It can be fooled by reassigned prototypes and fails across realms —\nuse `Array.isArray` \u002F `Object.prototype.toString` for those cases.\n",{"id":2980,"difficulty":161,"q":2981,"a":2982},"super-in-constructor","Why must super() be called before this in a subclass constructor?","In a derived class, the instance (`this`) is created by the **parent**\nconstructor, so you must call `super()` first to initialize it. Accessing `this`\nbefore `super()` throws a `ReferenceError`.\n\n```js\nclass Animal { constructor(name) { this.name = name } }\nclass Dog extends Animal {\n  constructor(name) {\n    this.bark = true     \u002F\u002F ReferenceError — before super()\n    super(name)\n    this.bark = true     \u002F\u002F\n  }\n}\n```\n\nThis is a real difference from constructor functions, where `this` exists\nimmediately. The rule guarantees the parent has set up the object before the\nchild touches it.\n",{"id":2984,"difficulty":161,"q":2985,"a":2986},"singleton-constructor","How can a constructor enforce a singleton?","Cache the instance and return it on subsequent `new` calls — leveraging the\n\"return an object overrides this\" rule.\n\n```js\nclass Config {\n  constructor() {\n    if (Config.instance) return Config.instance\n    Config.instance = this\n  }\n}\nnew Config() === new Config()   \u002F\u002F true — same instance\n```\n\nBecause returning an object from a constructor replaces the new `this`, the\nsecond `new` gets the cached instance. (A module-level singleton or a frozen\nobject is often simpler.)\n",{"id":2988,"difficulty":88,"q":2989,"a":2990},"prototype-methods-vs-constructor","Should methods go in the constructor or on the prototype?","Put **methods on the prototype** (shared, one copy); put **per-instance data**\nin the constructor (on `this`).\n\n```js\nfunction User(name) {\n  this.name = name                    \u002F\u002F instance data\n}\nUser.prototype.greet = function () {   \u002F\u002F shared method\n  return `Hi, ${this.name}`\n}\n```\n\nDefining methods inside the constructor (`this.greet = function(){}`) creates a\nnew function per instance — wasteful. Classes handle this correctly by placing\nmethods on the prototype automatically.\n",{"id":2992,"difficulty":161,"q":2993,"a":2994},"new-with-bind","What happens when you use new on a bound function?","`new` **overrides** a bound `this` — the instance wins. Bound *arguments* are\nstill applied.\n\n```js\nfunction Point(x, y) { this.x = x; this.y = y }\nconst Bound = Point.bind({ ignored: true }, 10)  \u002F\u002F pre-bind x = 10\nconst p = new Bound(20)\np.x  \u002F\u002F 10 (bound arg kept)\np.y  \u002F\u002F 20\n\u002F\u002F the bound `this` ({ ignored: true }) is ignored — p is a fresh Point\n```\n\nThis reflects precedence: `new` beats explicit binding. It's the one case where\n`bind`'s \"permanent\" `this` doesn't hold.\n",{"id":2996,"difficulty":88,"q":2997,"a":2998},"class-not-hoisted","Can you use a constructor before it is defined?","**Function** constructors are hoisted (usable before their line); **class**\nconstructors are hoisted but in the temporal dead zone, so they're **not** usable\nearly.\n\n```js\nnew Fn()              \u002F\u002F works — function declaration hoisted\nfunction Fn() {}\n\nnew Cls()             \u002F\u002F ReferenceError — TDZ\nclass Cls {}\n```\n\nSo switching from a constructor function to a class can break code that\ninstantiated it above its declaration. Always declare classes before use.\n",{"id":3000,"difficulty":161,"q":3001,"a":3002},"abstract-base","How do you make an abstract base constructor that can't be instantiated?","Check `new.target` against the base and throw, so only subclasses can be\ncreated.\n\n```js\nclass Shape {\n  constructor() {\n    if (new.target === Shape) throw new Error('Shape is abstract')\n  }\n  area() { throw new Error('not implemented') }\n}\nclass Circle extends Shape { area() { return 1 } }\nnew Shape()   \u002F\u002F throws\nnew Circle()  \u002F\u002F\n```\n\nJavaScript has no built-in `abstract` keyword, so `new.target` (plus throwing\nfrom unimplemented methods) is the idiom for abstract base classes.\n",{"id":3004,"difficulty":161,"q":3005,"a":3006},"reflect-construct","What is Reflect.construct?","The functional form of `new` — it invokes a constructor and optionally lets you\nspecify a different prototype (`newTarget`), useful in metaprogramming and for\nsubclassing built-ins.\n\n```js\nconst obj = Reflect.construct(Array, [1, 2, 3])   \u002F\u002F like new Array(1,2,3)\n\u002F\u002F third arg sets new.target \u002F the prototype to use:\nReflect.construct(Base, args, Derived)\n```\n\nIt's how you invoke a constructor dynamically (with an args array) and control\nthe resulting prototype — the building block frameworks use for advanced\ninstantiation.\n",{"id":3008,"difficulty":88,"q":3009,"a":3010},"chaining-constructors","How do constructor functions call a parent constructor?","Call the parent with `Parent.call(this, args)` so the parent initializes the\nchild's instance fields.\n\n```js\nfunction Animal(name) { this.name = name }\nfunction Dog(name, breed) {\n  Animal.call(this, name)   \u002F\u002F parent sets this.name\n  this.breed = breed\n}\n```\n\nThis is the pre-class way to \"chain\" constructors. With classes, `super(name)`\ndoes the same thing, and is required before using `this` in a subclass.\n",{"id":3012,"difficulty":96,"q":3013,"a":3014},"typeof-constructor","What does typeof return for a constructor or class?","`'function'` — both constructor functions and classes are functions under the\nhood.\n\n```js\nfunction Fn() {}\nclass Cls {}\ntypeof Fn    \u002F\u002F 'function'\ntypeof Cls   \u002F\u002F 'function'\n```\n\nClasses are special functions (strict mode, non-enumerable methods, must be\ncalled with `new`), but `typeof` doesn't distinguish them. To tell a class from\na regular function, you'd inspect the source or try calling without `new`.\n",{"id":3016,"difficulty":88,"q":3017,"a":3018},"pure-constructor","Should constructors have side effects?","Keep constructors **focused on initialization**. Heavy work — network calls,\nDOM access, throwing on async failures — makes objects hard to create, test, and\nreason about.\n\n```js\n\u002F\u002F side-effectful constructor\nclass User { constructor(id) { this.data = fetch(`\u002Fu\u002F${id}`) } }\n\n\u002F\u002F construct simply, do work in a method\u002Fstatic factory\nclass User {\n  constructor(data) { this.data = data }\n  static async load(id) { return new User(await (await fetch(`\u002Fu\u002F${id}`)).json()) }\n}\n```\n\nA common pattern is a **static async factory** (`User.load`) that does the I\u002FO\nand then constructs a plain instance — constructors can't be async.\n",{"id":3020,"difficulty":96,"q":3021,"a":3022},"new-object-vs-literal","Why prefer object literals over new Object?","`{}` is shorter, clearer, and slightly faster than `new Object()`, with no\ndownside. The same goes for `[]` over `new Array()` and `\u002Fregex\u002F` over\n`new RegExp()` for static patterns.\n\n```js\nconst a = {}            \u002F\u002F idiomatic\nconst b = new Object()  \u002F\u002F verbose, no benefit\n```\n\nUse `new` for types that genuinely need a constructor (`Date`, `Map`, `Set`,\n`Promise`, custom classes), and literals for the primitives-with-literals\n(objects, arrays, regexes).\n",{"id":3024,"difficulty":88,"q":3025,"a":3026},"constructor-returning-this","How do you enable method chaining from a constructor's methods?","Have each method `return this`, so calls can be chained on the instance.\n\n```js\nclass QueryBuilder {\n  constructor() { this.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 QueryBuilder().where('a=1').order('b').build()\n```\n\nReturning `this` (the instance) from methods is the builder\u002Ffluent pattern. It\nworks because methods are called on the instance, so `this` is consistent across\nthe chain.\n",{"id":3028,"difficulty":161,"q":3029,"a":3030},"private-with-closures","How do you make private data with a constructor function?","Use closures: declare variables inside the constructor and expose only methods\nthat close over them — the variables aren't accessible as properties.\n\n```js\nfunction Counter() {\n  let count = 0                          \u002F\u002F private\n  this.increment = () => ++count\n  this.value = () => count\n}\nconst c = new Counter()\nc.increment()\nc.value()   \u002F\u002F 1\nc.count     \u002F\u002F undefined — truly private\n```\n\nThe trade-off: these methods are per-instance (closures), not shared on the\nprototype. Modern classes offer `#private` fields for shared-method privacy\nwithout closures.\n",{"description":86},"JavaScript constructor interview questions — what the new operator does, constructor functions, returning values, new.target, and common new-related bugs.","javascript\u002Fobjects\u002Fnew-constructors","The new Operator & Constructors","5aotjqlkjQas6w28TNEYJdSAiTtsD8hnRDnlHSFl6ys",{"id":3037,"title":3038,"body":3039,"description":86,"difficulty":88,"extension":89,"framework":10,"frameworkSlug":8,"meta":3043,"navigation":91,"order":11,"path":3044,"questions":3045,"related":224,"seo":3165,"seoDescription":3166,"stem":3167,"subtopic":3168,"topic":46,"topicSlug":48,"updated":228,"__hash__":3169},"qa\u002Fjavascript\u002Fobjects\u002Fobjects-properties.md","Objects Properties",{"type":83,"value":3040,"toc":3041},[],{"title":86,"searchDepth":29,"depth":29,"links":3042},[],{},"\u002Fjavascript\u002Fobjects\u002Fobjects-properties",[3046,3050,3054,3058,3062,3066,3070,3074,3078,3082,3086,3090,3094,3098,3102,3106,3110,3114,3118,3122,3126,3130,3134,3138,3142,3146,3149,3153,3157,3161],{"id":3047,"difficulty":96,"q":3048,"a":3049},"create-object","What are the ways to create an object in JavaScript?","Several, each with different use cases:\n\n```js\nconst a = {}                       \u002F\u002F object literal (most common)\nconst b = new Object()             \u002F\u002F constructor (rarely used)\nconst c = Object.create(proto)     \u002F\u002F with an explicit prototype\nfunction Point(x) { this.x = x }   \u002F\u002F constructor function\nconst d = new Point(1)\nclass P {}                         \u002F\u002F class\nconst e = new P()\n```\n\nThe **object literal** `{}` is by far the most common. `Object.create(proto)`\nis the only one that lets you set the prototype directly (or create a\nprototype-less object with `Object.create(null)`). Constructor functions and\nclasses are for producing many similar objects.\n",{"id":3051,"difficulty":96,"q":3052,"a":3053},"access-properties","What is the difference between dot and bracket notation?","**Dot notation** (`obj.name`) is concise but only works for fixed, valid\nidentifier keys. **Bracket notation** (`obj['name']`) accepts any string or a\ncomputed expression — required for dynamic keys, keys with spaces\u002Fspecial\ncharacters, or numeric-like keys.\n\n```js\nobj.firstName          \u002F\u002F static key\nobj['first-name']      \u002F\u002F key with a hyphen — dot won't work\nconst key = 'age'\nobj[key]               \u002F\u002F dynamic key from a variable\n```\n\nUse dot notation by default; reach for brackets when the key is dynamic or not\na valid identifier.\n",{"id":3055,"difficulty":96,"q":3056,"a":3057},"property-shorthand","What are shorthand properties and computed property names?","**Shorthand** lets you omit the value when a variable has the same name as the\nkey. **Computed names** let you use an expression as a key inside a literal.\n\n```js\nconst name = 'Ada', age = 36\nconst user = { name, age }              \u002F\u002F { name: 'Ada', age: 36 }\n\nconst field = 'email'\nconst obj = { [field]: 'a@b.com', [`is${field}`]: true }\n\u002F\u002F { email: 'a@b.com', isemail: true }\n\nconst methods = { greet() { return 'hi' } } \u002F\u002F method shorthand\n```\n\nThese ES6 features make object construction terser and enable dynamic keys\nwithout a separate assignment.\n",{"id":3059,"difficulty":161,"q":3060,"a":3061},"property-descriptor","What is a property descriptor?","Every property has a **descriptor** describing its attributes. Data properties\nhave `value`, `writable`, `enumerable`, and `configurable`; accessor properties\nhave `get`, `set`, `enumerable`, `configurable`.\n\n```js\nconst obj = {}\nObject.defineProperty(obj, 'id', {\n  value: 1,\n  writable: false,     \u002F\u002F can't reassign\n  enumerable: false,   \u002F\u002F hidden from for...in \u002F Object.keys\n  configurable: false, \u002F\u002F can't delete or redefine\n})\nObject.getOwnPropertyDescriptor(obj, 'id')\n```\n\nProperties created normally default all flags to `true`; `defineProperty`\ndefaults them to `false`. Descriptors let you create read-only or\nnon-enumerable properties — used heavily by the language internals.\n",{"id":3063,"difficulty":88,"q":3064,"a":3065},"getters-setters","What are getters and setters?","Accessor properties that run a function on read (`get`) or write (`set`),\nletting a property be computed or validated while still being accessed like a\nnormal property.\n\n```js\nconst temp = {\n  celsius: 20,\n  get fahrenheit() { return this.celsius * 1.8 + 32 },\n  set fahrenheit(f) { this.celsius = (f - 32) \u002F 1.8 },\n}\ntemp.fahrenheit      \u002F\u002F 68 (computed)\ntemp.fahrenheit = 212\ntemp.celsius         \u002F\u002F 100\n```\n\nThey're useful for derived values, validation, and encapsulation. Define them\nwith `get`\u002F`set` syntax in a literal\u002Fclass, or via `Object.defineProperty`.\n",{"id":3067,"difficulty":96,"q":3068,"a":3069},"object-keys-values-entries","What do Object.keys, Object.values and Object.entries return?","They return arrays of an object's **own enumerable** string-keyed properties:\n\n```js\nconst o = { a: 1, b: 2 }\nObject.keys(o)    \u002F\u002F ['a', 'b']\nObject.values(o)  \u002F\u002F [1, 2]\nObject.entries(o) \u002F\u002F [['a', 1], ['b', 2]]\n\nfor (const [k, v] of Object.entries(o)) console.log(k, v)\n```\n\nThey ignore inherited and non-enumerable properties (and symbol keys). They're\nthe standard way to iterate objects, and `Object.fromEntries` reverses\n`entries` back into an object.\n",{"id":3071,"difficulty":88,"q":3072,"a":3073},"object-assign","What does Object.assign do?","`Object.assign(target, ...sources)` copies **own enumerable** properties from\nthe sources onto the target (a **shallow** copy) and returns the target.\n\n```js\nconst merged = Object.assign({}, defaults, overrides) \u002F\u002F merge into a new object\nconst clone = Object.assign({}, original)             \u002F\u002F shallow clone\n```\n\nIt only copies one level deep — nested objects are shared by reference. The\nspread operator `{ ...a, ...b }` does the same shallow merge more concisely and\nis usually preferred. `Object.assign` also triggers setters on the target.\n",{"id":3075,"difficulty":96,"q":3076,"a":3077},"spread-objects","How does the object spread operator work?","`{ ...obj }` copies an object's own enumerable properties into a new object — a\nconcise shallow copy\u002Fmerge. Later spreads override earlier keys.\n\n```js\nconst updated = { ...user, name: 'Grace' } \u002F\u002F copy + override one field\nconst merged = { ...defaults, ...options }   \u002F\u002F options win on conflicts\n```\n\nLike `Object.assign`, it's **shallow** — nested objects are shared. It's the\nidiomatic way to do immutable updates (especially in React). Spread copies\nvalues, not getters (it evaluates them).\n",{"id":3079,"difficulty":88,"q":3080,"a":3081},"delete-property","How do you remove a property from an object?","The `delete` operator removes a property entirely (so `'key' in obj` becomes\nfalse), returning `true` on success.\n\n```js\nconst obj = { a: 1, b: 2 }\ndelete obj.a\n'a' in obj  \u002F\u002F false\n```\n\nCaveats: `delete` only removes **own** properties (not inherited ones), can't\ndelete `configurable: false` properties, and can deoptimize objects in hot\npaths. For immutable removal, use destructuring: `const { a, ...rest } = obj`.\nSetting to `undefined` keeps the key; `delete` removes it.\n",{"id":3083,"difficulty":88,"q":3084,"a":3085},"check-property-exists","How do you check if a property exists on an object?","Three common approaches, each subtly different:\n\n```js\n'key' in obj                       \u002F\u002F true for own AND inherited properties\nobj.hasOwnProperty('key')          \u002F\u002F own properties only\nObject.hasOwn(obj, 'key')          \u002F\u002F own only (modern, safer)\nobj.key !== undefined              \u002F\u002F fails if the value IS undefined\n```\n\nUse `in` when inherited properties count; use `Object.hasOwn` (ES2022) for own\nproperties — it's safer than `hasOwnProperty`, which can be shadowed or missing\non `Object.create(null)` objects. Checking `=== undefined` is unreliable.\n",{"id":3087,"difficulty":161,"q":3088,"a":3089},"enumerable","What does \"enumerable\" mean for a property?","Enumerable properties show up in `for...in` loops, `Object.keys`, and spread;\nnon-enumerable ones are hidden from them (but still accessible directly).\n\n```js\nconst obj = { visible: 1 }\nObject.defineProperty(obj, 'hidden', { value: 2, enumerable: false })\nObject.keys(obj)             \u002F\u002F ['visible']\nobj.hidden                   \u002F\u002F 2 (still readable)\nObject.getOwnPropertyNames(obj) \u002F\u002F ['visible', 'hidden'] — includes non-enumerable\n```\n\nBuilt-in methods (like array methods on the prototype) are non-enumerable, so\nthey don't appear when you iterate. `getOwnPropertyNames` lists all own\nproperties regardless of enumerability.\n",{"id":3091,"difficulty":88,"q":3092,"a":3093},"for-in","What does for...in iterate over, and what is its pitfall?","`for...in` iterates **enumerable string keys**, including **inherited** ones\nfrom the prototype chain — which is its main pitfall.\n\n```js\nfor (const key in obj) {\n  if (Object.hasOwn(obj, key)) {   \u002F\u002F guard against inherited keys\n    console.log(key, obj[key])\n  }\n}\n```\n\nAlways guard with `Object.hasOwn`\u002F`hasOwnProperty` unless you want inherited\nkeys. For arrays, prefer `for...of` (values) or a normal loop — `for...in`\niterates indices as strings and includes non-index enumerable properties.\n",{"id":3095,"difficulty":88,"q":3096,"a":3097},"object-freeze","What is the difference between Object.freeze, seal and preventExtensions?","Three levels of locking down an object:\n\n- **`preventExtensions`** — can't add new properties; existing ones stay\n  writable\u002Fdeletable.\n- **`seal`** — preventExtensions + can't delete or reconfigure properties; values\n  still writable.\n- **`freeze`** — seal + can't change values. Fully immutable (shallowly).\n\n```js\nconst obj = Object.freeze({ a: 1, nested: { b: 2 } })\nobj.a = 9         \u002F\u002F ignored (throws in strict mode)\nobj.nested.b = 9  \u002F\u002F still works — freeze is SHALLOW\n```\n\nAll three are shallow. Check with `Object.isFrozen`\u002F`isSealed`. For deep\nimmutability, recursively freeze.\n",{"id":3099,"difficulty":161,"q":3100,"a":3101},"shallow-vs-deep-clone","How do you deep clone an object?","Shallow copies (`{ ...obj }`, `Object.assign`) share nested references. For a\nfully independent copy, use **`structuredClone`** (modern, handles cycles,\nDates, Maps), or a library.\n\n```js\nconst deep = structuredClone(original)   \u002F\u002F best built-in option\n\nconst viaJson = JSON.parse(JSON.stringify(original)) \u002F\u002F loses functions,\n\u002F\u002F undefined, Symbols; breaks on Dates\u002FMaps\u002Fcycles\n```\n\n`structuredClone` is the standard now; the `JSON` trick works only for plain\nJSON-safe data and silently mangles everything else.\n",{"id":3103,"difficulty":88,"q":3104,"a":3105},"object-references","Are objects compared by value or reference?","By **reference**. Two distinct objects with identical contents are not equal;\nonly two references to the *same* object are.\n\n```js\n{ a: 1 } === { a: 1 }   \u002F\u002F false (different objects)\nconst x = { a: 1 }\nconst y = x\nx === y                 \u002F\u002F true (same reference)\ny.a = 2; x.a            \u002F\u002F 2 — they share the object\n```\n\nAssigning an object copies the reference, not the object. This underlies\nshallow-copy bugs and why you need `structuredClone` for true independence.\n",{"id":3107,"difficulty":96,"q":3108,"a":3109},"optional-chaining-objects","How does optional chaining help with nested objects?","`?.` short-circuits to `undefined` if a reference is `null`\u002F`undefined`, instead\nof throwing — safe access into deep structures.\n\n```js\nuser?.address?.city           \u002F\u002F undefined if user or address is missing\nuser?.getName?.()             \u002F\u002F call only if it exists\ndata?.items?.[0]              \u002F\u002F safe index access\nconst city = user?.address?.city ?? 'unknown'\n```\n\nIt stops evaluating at the first nullish link. Pair it with `??` for defaults.\nDon't overuse it to mask data that *should* exist — it can hide bugs.\n",{"id":3111,"difficulty":88,"q":3112,"a":3113},"this-in-objects","What does this refer to in an object method?","In a regular-function method called as `obj.method()`, `this` is the object the\nmethod was called on. Extract the method, and `this` is lost.\n\n```js\nconst counter = {\n  count: 0,\n  inc() { this.count++ },\n}\ncounter.inc()              \u002F\u002F this === counter\nconst fn = counter.inc\nfn()                       \u002F\u002F this is undefined -> TypeError\n```\n\nUse method shorthand (a regular function) for methods that need `this`; avoid\narrow methods (their `this` is the outer scope, not the object).\n",{"id":3115,"difficulty":161,"q":3116,"a":3117},"object-create-null","What is Object.create(null) used for?","It creates an object with **no prototype** — a \"pure dictionary\" with no\ninherited properties or methods (`toString`, `hasOwnProperty`, etc.).\n\n```js\nconst dict = Object.create(null)\ndict.key = 'value'\ndict.toString          \u002F\u002F undefined — no Object.prototype\n'toString' in dict     \u002F\u002F false\n```\n\nUseful as a safe map where user-controlled keys won't collide with inherited\nproperty names (e.g. a key literally named `\"hasOwnProperty\"`). The trade-off:\nobject methods aren't available, so use `Object.keys(dict)` etc. (A `Map` is\noften a cleaner choice.)\n",{"id":3119,"difficulty":88,"q":3120,"a":3121},"object-vs-map","When should you use a Map instead of an object?","Use a **`Map`** when keys are dynamic or non-string, when you need ordering and\neasy size, or when you frequently add\u002Fremove entries.\n\n| | Object | Map |\n| --- | --- | --- |\n| Keys | strings\u002Fsymbols | **any type** |\n| Order | mostly insertion (quirky for integer keys) | guaranteed insertion |\n| Size | `Object.keys(o).length` | `map.size` |\n| Iteration | needs `Object.entries` | directly iterable |\n| Prototype keys | risk of collisions | none |\n\nUse a plain **object** for fixed, known-shape records and when you need JSON\nserialization (Maps don't `JSON.stringify` directly).\n",{"id":3123,"difficulty":161,"q":3124,"a":3125},"getownpropertynames","How do you list all properties including non-enumerable and symbols?","`Object.keys` misses non-enumerable and symbol keys. Use the fuller reflection\nmethods:\n\n```js\nObject.getOwnPropertyNames(obj)    \u002F\u002F all string keys (incl. non-enumerable)\nObject.getOwnPropertySymbols(obj)  \u002F\u002F symbol keys\nReflect.ownKeys(obj)               \u002F\u002F EVERYTHING: strings + symbols\n```\n\n`Reflect.ownKeys` is the complete list of own keys. These are needed for deep\ncloning, serialization, and metaprogramming where you must see every property.\n",{"id":3127,"difficulty":161,"q":3128,"a":3129},"property-order","In what order are object keys iterated?","Modern engines follow a spec order: **integer-like keys first, in ascending\nnumeric order**, then **string keys in insertion order**, then **symbol keys in\ninsertion order**.\n\n```js\nconst obj = { b: 1, 2: 1, a: 1, 1: 1 }\nObject.keys(obj) \u002F\u002F ['1', '2', 'b', 'a'] — numbers sorted, then strings as added\n```\n\nSo integer-like keys are *not* in insertion order — a surprise if you rely on\norder. If you need strict insertion order for all keys, use a **`Map`**.\n",{"id":3131,"difficulty":96,"q":3132,"a":3133},"method-vs-property","What is the difference between a method and a property?","A **property** holds a value; a **method** is a property whose value is a\nfunction, so it can be called.\n\n```js\nconst obj = {\n  name: 'Ada',           \u002F\u002F property\n  greet() { return 'hi' }, \u002F\u002F method (function-valued property)\n}\nobj.name      \u002F\u002F 'Ada'\nobj.greet()  \u002F\u002F 'hi'\n```\n\nMethods are just properties that happen to be functions — `typeof obj.greet`\nis `'function'`. Defining a method with shorthand also makes it non-arrow, so\n`this` works correctly.\n",{"id":3135,"difficulty":88,"q":3136,"a":3137},"tostring-override","How do you control how an object converts to a string or number?","Override `toString`\u002F`valueOf`, or implement `Symbol.toPrimitive` for full\ncontrol over coercion.\n\n```js\nconst money = {\n  amount: 100,\n  [Symbol.toPrimitive](hint) {\n    return hint === 'string' ? `$${this.amount}` : this.amount\n  },\n  toString() { return `$${this.amount}` },\n}\n`${money}`   \u002F\u002F '$100'\nmoney + 1    \u002F\u002F 101\n```\n\nWithout these, objects coerce to `[object Object]` (string) via `toString`.\n`Symbol.toPrimitive` takes precedence and receives a hint (`'string'`,\n`'number'`, `'default'`).\n",{"id":3139,"difficulty":88,"q":3140,"a":3141},"json-stringify-object","How does JSON.stringify handle objects?","It serializes **own enumerable** properties, but silently drops `undefined`,\nfunctions, and symbols, converts `NaN`\u002F`Infinity` to `null`, and calls a\n`toJSON()` method if present.\n\n```js\nJSON.stringify({ a: 1, b: undefined, c: () => {}, d: Symbol() })\n\u002F\u002F '{\"a\":1}'  — b, c, d dropped\n\nJSON.stringify(obj, ['a', 'b'])        \u002F\u002F replacer array: only these keys\nJSON.stringify(obj, null, 2)           \u002F\u002F pretty-print with 2-space indent\n```\n\n`BigInt` and circular references **throw**. The optional replacer and space\narguments control filtering and formatting.\n",{"id":3143,"difficulty":88,"q":3144,"a":3145},"chaining-optional-assignment","What does the logical assignment operator ||= and ??= do with objects?","They assign only when the left side is falsy (`||=`) or nullish (`??=`) — handy\nfor defaulting object properties.\n\n```js\nconst config = { timeout: 0 }\nconfig.timeout ||= 1000   \u002F\u002F 1000 overwrites valid 0\nconfig.timeout ??= 1000   \u002F\u002F 0    only fills null\u002Fundefined\nconfig.retries ??= 3      \u002F\u002F adds retries: 3\n```\n\n`??=` is the safe choice when `0`\u002F`''`\u002F`false` are valid values. They're\nshorthand for `x = x ?? value` and short-circuit (the right side isn't\nevaluated if no assignment happens).\n",{"id":2130,"difficulty":88,"q":3147,"a":3148},"How do you compare two objects for equality?","`===` only checks reference identity, so you must compare contents yourself for\n\"same data\" equality.\n\n```js\nconst shallowEqual = (a, b) => {\n  const ak = Object.keys(a), bk = Object.keys(b)\n  return ak.length === bk.length && ak.every((k) => a[k] === b[k])\n}\n```\n\nFor nested structures you need a recursive **deep equality** (lodash `isEqual`).\nThe `JSON.stringify(a) === JSON.stringify(b)` trick works only for simple data\nand is sensitive to key order and `undefined`.\n",{"id":3150,"difficulty":161,"q":3151,"a":3152},"defineproperties","What is the difference between defining a property and assigning it?","Plain assignment (`obj.x = 1`) creates an enumerable, writable, configurable\ndata property — or **triggers an inherited setter** if one exists.\n`Object.defineProperty` creates the property with explicit (default `false`)\nflags and **bypasses** setters.\n\n```js\nobj.x = 1   \u002F\u002F enumerable: true, writable: true, configurable: true\nObject.defineProperty(obj, 'y', { value: 2 })\n\u002F\u002F enumerable: false, writable: false, configurable: false\n```\n\nUse assignment for normal data; use `defineProperty` for read-only, hidden, or\naccessor properties, or to define multiple at once with `defineProperties`.\n",{"id":3154,"difficulty":96,"q":3155,"a":3156},"nullish-vs-or-default","How do you set default values when destructuring an object?","Provide defaults in the destructuring pattern; they apply only when the value\nis `undefined` (not `null` or other falsy values).\n\n```js\nconst { timeout = 1000, retries = 3, mode = 'auto' } = options\nconst { a: alias = 5 } = obj            \u002F\u002F rename + default\nfunction f({ x = 0, y = 0 } = {}) {}     \u002F\u002F default for the whole object too\n```\n\nThe `= {}` default on the parameter prevents a crash when the argument is\nomitted entirely. Defaults trigger only on `undefined`, so an explicit `null`\noverrides them.\n",{"id":3158,"difficulty":88,"q":3159,"a":3160},"copy-with-rest","How do you copy an object while omitting some properties?","Use destructuring with a **rest** pattern — the named keys are excluded, the\nrest collected into a new object.\n\n```js\nconst { password, ...safe } = user   \u002F\u002F `safe` has everything except password\nconst { [dynamicKey]: _, ...rest } = obj \u002F\u002F omit a dynamic key\n```\n\nThis is the idiomatic immutable \"remove a property\" — it produces a new object\nwithout mutating the original (unlike `delete`). Great for stripping sensitive\nfields before sending data.\n",{"id":3162,"difficulty":88,"q":3163,"a":3164},"object-grouping","How do you transform or group object data?","Convert to entries, transform, and convert back with `Object.fromEntries`:\n\n```js\n\u002F\u002F double every value\nconst doubled = Object.fromEntries(\n  Object.entries(obj).map(([k, v]) => [k, v * 2])\n)\n\u002F\u002F filter keys\nconst filtered = Object.fromEntries(\n  Object.entries(obj).filter(([, v]) => v > 10)\n)\n```\n\n`Object.entries` + array methods + `Object.fromEntries` is the functional\npattern for mapping\u002Ffiltering objects (which have no native `map`\u002F`filter`).\n`Object.groupBy` (ES2024) groups an array into an object by a key function.\n",{"description":86},"JavaScript object interview questions — creating objects, property descriptors, getters and setters, Object methods, enumeration, freezing and copying.","javascript\u002Fobjects\u002Fobjects-properties","Objects & Properties","8e9eu-hN4JNeXrO12JjJ3sUR5YmuDgSldUUI50UInGc",{"id":3171,"title":3172,"body":3173,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":3177,"navigation":91,"order":38,"path":3178,"questions":3179,"related":224,"seo":3283,"seoDescription":3284,"stem":3285,"subtopic":3172,"topic":46,"topicSlug":48,"updated":228,"__hash__":3286},"qa\u002Fjavascript\u002Fobjects\u002Fprototypal-inheritance.md","Prototypal Inheritance",{"type":83,"value":3174,"toc":3175},[],{"title":86,"searchDepth":29,"depth":29,"links":3176},[],{},"\u002Fjavascript\u002Fobjects\u002Fprototypal-inheritance",[3180,3184,3188,3192,3196,3200,3204,3208,3212,3216,3220,3224,3228,3232,3236,3240,3244,3248,3252,3256,3260,3263,3267,3271,3275,3279],{"id":3181,"difficulty":88,"q":3182,"a":3183},"what-is-prototypal-inheritance","What is prototypal inheritance?","A model where objects inherit directly from **other objects** (their prototype),\nrather than from classes. A missing property is looked up on the prototype\nchain, so one object can reuse another's properties and methods.\n\n```js\nconst animal = { eats: true, walk() { return 'walking' } }\nconst rabbit = Object.create(animal)\nrabbit.jumps = true\nrabbit.walk()  \u002F\u002F 'walking' — inherited\nrabbit.eats    \u002F\u002F true — inherited\n```\n\nJavaScript's inheritance is fundamentally object-to-object **delegation**. Even\n`class` is sugar over this prototypal mechanism.\n",{"id":3185,"difficulty":88,"q":3186,"a":3187},"object-create-inheritance","How do you implement inheritance with Object.create?","`Object.create(proto)` makes a new object whose prototype is `proto`, giving you\ndirect prototypal inheritance with no constructors.\n\n```js\nconst base = {\n  init(name) { this.name = name; return this },\n  describe() { return `I am ${this.name}` },\n}\nconst child = Object.create(base)\nchild.shout = function () { return this.describe().toUpperCase() }\n\nconst c = Object.create(child).init('Ada')\nc.shout()  \u002F\u002F 'I AM ADA'\n```\n\nEach level delegates to the one above. This is the most direct expression of\nprototypal inheritance — no `new`, no `prototype` juggling.\n",{"id":3189,"difficulty":161,"q":3190,"a":3191},"constructor-inheritance","How do you set up inheritance between constructor functions?","Call the parent constructor for the instance fields, and link the prototypes so\nmethods are inherited.\n\n```js\nfunction Animal(name) { this.name = name }\nAnimal.prototype.eat = function () { return `${this.name} eats` }\n\nfunction Dog(name) {\n  Animal.call(this, name)               \u002F\u002F inherit instance properties\n}\nDog.prototype = Object.create(Animal.prototype) \u002F\u002F inherit methods\nDog.prototype.constructor = Dog                 \u002F\u002F restore constructor\nDog.prototype.bark = function () { return 'woof' }\n```\n\nThis is the pre-ES6 pattern: `Parent.call(this)` for fields,\n`Object.create(Parent.prototype)` for the method chain, and reset\n`constructor`. `class extends` does all this for you.\n",{"id":3193,"difficulty":88,"q":3194,"a":3195},"class-vs-prototypal","What is the difference between classical and prototypal inheritance?","- **Classical** (Java\u002FC++): classes are blueprints; objects are **instances**\n  that copy structure from the class hierarchy.\n- **Prototypal** (JavaScript): objects **delegate** to live prototype objects;\n  there's no copying, and the link is dynamic.\n\n```js\n\u002F\u002F prototypal: changing the prototype affects existing objects live\nconst proto = { greet() { return 'hi' } }\nconst obj = Object.create(proto)\nproto.greet = () => 'hello'\nobj.greet()  \u002F\u002F 'hello' — live delegation, not a copy\n```\n\nJavaScript's `class` *looks* classical but is prototypal underneath. The key\ndifference is delegation (live links) vs copying (static blueprints).\n",{"id":3197,"difficulty":161,"q":3198,"a":3199},"super-in-prototypal","How do you call a parent method from a child (without class)?","Reference the parent prototype's method and invoke it with the right `this` via\n`call`.\n\n```js\nDog.prototype.eat = function () {\n  const base = Animal.prototype.eat.call(this)  \u002F\u002F call parent, keep `this`\n  return base + ' noisily'\n}\n```\n\nWith `class`, `super.method()` does this cleanly. Without classes, you must\nexplicitly grab `Parent.prototype.method` and `call` it with the instance, or\nthe parent method would run with the wrong `this`.\n",{"id":3201,"difficulty":96,"q":3202,"a":3203},"override-method","How does method overriding work with prototypes?","Define a method with the same name lower in the chain (on the child); it shadows\nthe parent's version because lookup stops at the first match.\n\n```js\nconst animal = { speak() { return '...' } }\nconst dog = Object.create(animal)\ndog.speak = function () { return 'Woof' }  \u002F\u002F overrides\ndog.speak()                                 \u002F\u002F 'Woof'\nObject.getPrototypeOf(dog).speak()          \u002F\u002F '...' (parent still reachable)\n```\n\nThe override is just a closer own\u002Fprototype property. The parent method remains\naccessible via the prototype if you need to call it (the manual `super`).\n",{"id":3205,"difficulty":88,"q":3206,"a":3207},"factory-functions","What are factory functions and how do they relate to inheritance?","A factory function returns a new object without `new` or classes — often using\nclosures for state and composition (rather than prototype chains) for behavior.\n\n```js\nfunction createUser(name) {\n  return {\n    name,\n    greet() { return `Hi, ${name}` },\n  }\n}\nconst u = createUser('Ada')\n```\n\nFactories favor **composition over inheritance**: instead of inheriting from a\nprototype, you assemble objects from pieces. Trade-off: methods aren't shared on\na prototype (each object gets its own), costing some memory for many instances.\n",{"id":3209,"difficulty":88,"q":3210,"a":3211},"mixins","What are mixins?","A way to share behavior across unrelated objects\u002Fclasses by **copying methods**\nin, instead of inheriting — JavaScript's answer to the lack of multiple\ninheritance.\n\n```js\nconst serializable = { serialize() { return JSON.stringify(this) } }\nconst comparable = { equals(o) { return this.id === o.id } }\n\nclass Model {}\nObject.assign(Model.prototype, serializable, comparable)\n```\n\nMixins let a class gain capabilities from several sources. They're a flexible\nalternative to deep inheritance — compose the behaviors a type needs rather than\nforcing a single hierarchy.\n",{"id":3213,"difficulty":161,"q":3214,"a":3215},"diamond-problem","Does JavaScript have the diamond problem?","Not in the classic multiple-inheritance sense, because each object has a\n**single** prototype chain — there's no ambiguity over which parent a method\ncomes from. But **mixins** can reintroduce conflicts when two mixins define the\nsame method.\n\n```js\nconst a = { run() { return 'a' } }\nconst b = { run() { return 'b' } }\nObject.assign(target, a, b)\ntarget.run()  \u002F\u002F 'b' — last one wins, silently\n```\n\nWith `Object.assign`, the last source wins on key collisions (no error). So\nsingle-prototype inheritance avoids diamonds, but you must manage mixin method\nclashes yourself.\n",{"id":3217,"difficulty":88,"q":3218,"a":3219},"prototype-vs-instance-property","Should shared state go on the prototype?","No — only **methods** (and true constants) belong on the prototype. Mutable\nshared state on a prototype is accidentally shared by all instances.\n\n```js\nfunction Cart() {}\nCart.prototype.items = []        \u002F\u002F ALL carts share one array\nconst a = new Cart(), b = new Cart()\na.items.push('x')\nb.items                          \u002F\u002F ['x'] — leaked!\n\nfunction Cart2() { this.items = [] }  \u002F\u002F per-instance state in the constructor\n```\n\nPut per-instance data on `this` in the constructor; put shared behavior on the\nprototype. (This mirrors the Java \"mutable static field\" trap.)\n",{"id":3221,"difficulty":161,"q":3222,"a":3223},"inherit-static","Are static-like properties inherited?","Constructor functions have their **own** prototype chain\n(`Child.__proto__ === Parent` when using `class extends`), so \"static\"\nproperties on the parent constructor are inherited by the child constructor.\n\n```js\nclass Parent { static create() { return new this() } }\nclass Child extends Parent {}\nChild.create()   \u002F\u002F works — static method inherited; `this` is Child\n```\n\n`extends` links both chains: instance methods via `Child.prototype ->\nParent.prototype`, and statics via `Child -> Parent`. With plain constructor\nfunctions you'd wire statics up manually.\n",{"id":3225,"difficulty":161,"q":3226,"a":3227},"object-create-second-arg","What is the second argument to Object.create?","A **property descriptors** object — it lets you define own properties (with\nwritable\u002Fenumerable\u002Fconfigurable flags) at the same time as setting the\nprototype.\n\n```js\nconst obj = Object.create(proto, {\n  id: { value: 1, enumerable: true },\n  secret: { value: 42, enumerable: false },\n})\n```\n\nIt's the same descriptor format as `Object.defineProperties`. Rarely needed, but\nit's how you create an object with both a chosen prototype and precisely\nconfigured own properties in one call.\n",{"id":3229,"difficulty":161,"q":3230,"a":3231},"parasitic-inheritance","What is parasitic \u002F functional inheritance?","An older pattern where a factory creates a base object, then **augments** it with\nextra properties\u002Fmethods before returning it — inheritance without prototypes.\n\n```js\nfunction createAnimal(name) {\n  const obj = { name }\n  obj.eat = () => `${name} eats`\n  return obj\n}\nfunction createDog(name) {\n  const dog = createAnimal(name)   \u002F\u002F \"inherit\" by starting from a base\n  dog.bark = () => 'woof'          \u002F\u002F augment\n  return dog\n}\n```\n\nIt uses composition\u002Fclosures instead of the prototype chain. Methods aren't\nshared (memory cost), but it's simple and avoids `this`\u002F`new` pitfalls.\n",{"id":3233,"difficulty":88,"q":3234,"a":3235},"hasownproperty-inheritance","Why can iterating an inheriting object surprise you?","`for...in` walks inherited enumerable properties too, so an object that inherits\nfrom another can expose more keys than you expect.\n\n```js\nconst proto = { shared: 1 }\nconst obj = Object.create(proto)\nobj.own = 2\nfor (const k in obj) console.log(k)   \u002F\u002F 'own' AND 'shared'\n```\n\nGuard with `Object.hasOwn(obj, k)`, or iterate `Object.keys(obj)` (own only).\nThis is why adding enumerable properties to built-in prototypes is dangerous —\nit pollutes every `for...in`.\n",{"id":3237,"difficulty":161,"q":3238,"a":3239},"super-property-vs-method","How does inheritance interact with getters and setters?","Inherited accessors run with the instance as `this`, so a child can override a\ngetter\u002Fsetter while the parent's still computes against the child's data.\n\n```js\nconst base = {\n  get label() { return `[${this.name}]` },\n}\nconst item = Object.create(base)\nitem.name = 'box'\nitem.label   \u002F\u002F '[box]' — inherited getter, `this` is item\n```\n\nOverriding an inherited setter and writing to the property creates an own data\nproperty unless the child also defines an accessor — a subtle source of bugs\nwhen mixing data and accessor properties across a chain.\n",{"id":3241,"difficulty":88,"q":3242,"a":3243},"composition-over-inheritance-js","Why is composition often preferred over inheritance in JavaScript?","Deep inheritance chains are rigid: a change in a base ripples to all\ndescendants, and an object is locked into one hierarchy. **Composition** builds\nobjects from small, swappable behaviors, which is more flexible.\n\n```js\nconst withTimestamp = (o) => ({ ...o, createdAt: Date.now() })\nconst withId = (o) => ({ ...o, id: crypto.randomUUID() })\nconst record = withId(withTimestamp({ name: 'Ada' }))\n```\n\nCompose capabilities (functions, mixins, delegation) instead of inheriting them.\nThis avoids the fragile-base-class problem and the \"gorilla holding the banana\nand the entire jungle\" inheritance trap.\n",{"id":3245,"difficulty":88,"q":3246,"a":3247},"instanceof-inheritance","How do you check an object's type through an inheritance chain?","`instanceof` returns true for any constructor whose `prototype` is in the chain,\nso it sees inherited types.\n\n```js\nclass Shape {}\nclass Circle extends Shape {}\nconst c = new Circle()\nc instanceof Circle   \u002F\u002F true\nc instanceof Shape    \u002F\u002F true (ancestor)\n```\n\nFor prototypal (non-class) inheritance, use\n`proto.isPrototypeOf(obj)` to ask \"is this object in obj's chain?\" — the\ndelegation-style equivalent of `instanceof`.\n",{"id":3249,"difficulty":88,"q":3250,"a":3251},"isprototypeof","What does isPrototypeOf do?","`proto.isPrototypeOf(obj)` returns true if `proto` appears anywhere in `obj`'s\nprototype chain — the object-oriented complement to `instanceof` (which works\nwith constructors).\n\n```js\nconst animal = {}\nconst dog = Object.create(animal)\nanimal.isPrototypeOf(dog)            \u002F\u002F true\nObject.prototype.isPrototypeOf(dog)  \u002F\u002F true\n```\n\nIt's the natural type check for prototypal inheritance built with\n`Object.create`, where there's no constructor to use with `instanceof`.\n",{"id":3253,"difficulty":88,"q":3254,"a":3255},"shared-method-this","How does this behave in an inherited method?","An inherited method is called on the instance, so `this` is the **instance**,\nnot the prototype where the method is defined.\n\n```js\nconst proto = { whoAmI() { return this.name } }\nconst a = Object.create(proto); a.name = 'A'\nconst b = Object.create(proto); b.name = 'B'\na.whoAmI()  \u002F\u002F 'A'\nb.whoAmI()  \u002F\u002F 'B' — same method, different `this`\n```\n\nThis is what makes shared prototype methods useful: one definition operates on\nwhichever instance invokes it. Lose the receiver (extract the method) and `this`\nbreaks, as always.\n",{"id":3257,"difficulty":88,"q":3258,"a":3259},"multiple-levels","Can you have multiple levels of prototypal inheritance?","Yes — chains can be arbitrarily deep, each level delegating to the next.\n\n```js\nconst a = { x: 1 }\nconst b = Object.create(a); b.y = 2\nconst c = Object.create(b); c.z = 3\nc.x  \u002F\u002F 1 (from a, two levels up)\nc.y  \u002F\u002F 2 (from b)\nc.z  \u002F\u002F 3 (own)\n```\n\nLookup walks `c -> b -> a -> Object.prototype -> null`. Deep chains work but get\nharder to reason about and slightly slower to traverse; flatter structures (or\ncomposition) are usually clearer.\n",{"id":2948,"difficulty":161,"q":3261,"a":3262},"What is new.target and how does it help with inheritance?","`new.target` is the constructor that was invoked with `new` (or `undefined` for\na normal call). It lets a base constructor know which subclass is being built and\nenforce `new`.\n\n```js\nfunction Base() {\n  if (!new.target) throw new Error('Use new')\n  console.log(new.target.name)   \u002F\u002F logs the actual subclass\n}\nclass Sub extends Base {}\nnew Sub()   \u002F\u002F logs 'Sub'\n```\n\nUseful for abstract base classes (throw if `new.target === Base`) and for\nfactory logic that depends on the concrete type being constructed.\n",{"id":3264,"difficulty":88,"q":3265,"a":3266},"prototype-chain-json","Does JSON.stringify include inherited properties?","No — `JSON.stringify` serializes **own enumerable** properties only, ignoring\nanything inherited from the prototype.\n\n```js\nconst proto = { inherited: 1 }\nconst obj = Object.create(proto)\nobj.own = 2\nJSON.stringify(obj)   \u002F\u002F '{\"own\":2}' — inherited is omitted\n```\n\nSo data on a prototype won't be serialized. If you need inherited values in\nJSON, copy them onto the object first (`{ ...proto, ...obj }`) or implement\n`toJSON`.\n",{"id":3268,"difficulty":88,"q":3269,"a":3270},"when-classes-vs-prototypes","Should you use classes or raw prototypes today?","For most code, **use `class`** — it's clearer, standard, and handles the\nprototype wiring (`extends`\u002F`super`\u002Fstatics) correctly. Reach for raw\nprototypes\u002F`Object.create` only for low-level work, OLOO-style delegation, or\nunderstanding internals.\n\n```js\n\u002F\u002F idiomatic modern inheritance\nclass Animal { constructor(n) { this.name = n } speak() {} }\nclass Dog extends Animal { speak() { return 'Woof' } }\n```\n\nClasses and prototypes are the same machinery; classes just give you a safer,\nmore readable interface. Knowing prototypes still matters for debugging and edge\ncases.\n",{"id":3272,"difficulty":88,"q":3273,"a":3274},"augmenting-instances","What is the cost of adding methods to instances vs the prototype?","Methods added to each **instance** are duplicated per object (more memory);\nmethods on the **prototype** are shared (one copy).\n\n```js\n\u002F\u002F a new function per instance\nfunction User(name) {\n  this.name = name\n  this.greet = function () { return this.name }\n}\n\u002F\u002F shared once\nUser.prototype.greet = function () { return this.name }\n```\n\nFor a handful of objects it doesn't matter; for thousands, prototype methods\nsave significant memory. Factory functions trade this away for closure-based\nprivacy — a deliberate choice.\n",{"id":3276,"difficulty":88,"q":3277,"a":3278},"delegation-events","How does delegation in prototypes relate to event delegation?","Both are \"delegation\" but different ideas. **Prototypal delegation** forwards\n*property lookups* up the prototype chain. **Event delegation** attaches one\nlistener to a parent that handles events from many children via bubbling.\n\n```js\n\u002F\u002F event delegation (unrelated to prototypes)\nlist.addEventListener('click', (e) => {\n  if (e.target.matches('li')) handle(e.target)\n})\n```\n\nThey share a name and a \"let something else handle it\" spirit, but operate in\ncompletely different parts of the language\u002FDOM — a common point of confusion.\n",{"id":3280,"difficulty":161,"q":3281,"a":3282},"clone-with-prototype","How do you clone an object while preserving its prototype?","Spread\u002F`Object.assign` copy own properties but give the clone a **plain object\nprototype**, losing the original's prototype. Preserve it explicitly:\n\n```js\nconst clone = Object.assign(\n  Object.create(Object.getPrototypeOf(original)),\n  original,\n)\n\u002F\u002F or structuredClone — but it does NOT preserve custom prototypes either\n```\n\n`{ ...obj }` and `structuredClone` both drop the custom prototype (the clone\nbecomes a plain object). To keep behavior, create the clone with\n`Object.create(getPrototypeOf(original))` then copy the own properties.\n",{"description":86},"JavaScript prototypal inheritance interview questions — Object.create, delegation, constructor inheritance, classical vs prototypal, and sharing behavior between objects.","javascript\u002Fobjects\u002Fprototypal-inheritance","GvqUS3PImrZ3Q2MJBGdT3949HLkhsnt0F70ivtrPQog",{"id":3288,"title":3289,"body":3290,"description":86,"difficulty":161,"extension":89,"framework":10,"frameworkSlug":8,"meta":3294,"navigation":91,"order":29,"path":3295,"questions":3296,"related":224,"seo":3412,"seoDescription":3413,"stem":3414,"subtopic":3415,"topic":46,"topicSlug":48,"updated":228,"__hash__":3416},"qa\u002Fjavascript\u002Fobjects\u002Fprototypes-chain.md","Prototypes Chain",{"type":83,"value":3291,"toc":3292},[],{"title":86,"searchDepth":29,"depth":29,"links":3293},[],{},"\u002Fjavascript\u002Fobjects\u002Fprototypes-chain",[3297,3301,3305,3309,3313,3317,3321,3325,3329,3332,3336,3340,3344,3348,3352,3356,3360,3364,3368,3372,3376,3380,3384,3388,3392,3396,3400,3404,3408],{"id":3298,"difficulty":88,"q":3299,"a":3300},"what-is-prototype","What is a prototype in JavaScript?","Every object has an internal link to another object called its **prototype**.\nWhen you access a property that the object doesn't have, JavaScript looks it up\non the prototype, then that object's prototype, and so on — the **prototype\nchain**. This is how objects inherit behavior in JavaScript.\n\n```js\nconst arr = [1, 2, 3]\narr.map(x => x)  \u002F\u002F `map` isn't on `arr`; it's found on Array.prototype\n```\n\nPrototypes are how methods are **shared** across many instances without copying\nthem onto each object — the foundation of JavaScript's object model.\n",{"id":3302,"difficulty":161,"q":3303,"a":3304},"proto-vs-prototype","What is the difference between __proto__ and prototype?","They're related but distinct:\n\n- **`prototype`** is a property of **constructor functions** (and classes). It's\n  the object that becomes the prototype of instances created with `new`.\n- **`__proto__`** (or `Object.getPrototypeOf`) is the actual **prototype link**\n  on every object — pointing to the object it inherits from.\n\n```js\nfunction Dog() {}\nconst d = new Dog()\nd.__proto__ === Dog.prototype          \u002F\u002F true\nObject.getPrototypeOf(d) === Dog.prototype \u002F\u002F true (preferred check)\n```\n\nSo `Constructor.prototype` is what *instances* get as their `__proto__`. Use\n`Object.getPrototypeOf`\u002F`setPrototypeOf` instead of the legacy `__proto__`.\n",{"id":3306,"difficulty":88,"q":3307,"a":3308},"prototype-chain-lookup","How does property lookup work along the prototype chain?","When you read `obj.prop`, the engine checks `obj` first; if not found, it\nfollows `obj`'s prototype, then that object's prototype, until it finds the\nproperty or reaches `null` (returning `undefined`).\n\n```js\nconst animal = { eats: true }\nconst dog = Object.create(animal)\ndog.barks = true\ndog.barks   \u002F\u002F true (own)\ndog.eats    \u002F\u002F true (inherited from animal)\ndog.flies   \u002F\u002F undefined (not found anywhere)\n```\n\nWriting a property, by contrast, always creates\u002Fupdates an **own** property on\nthe object itself — it doesn't modify the prototype (unless an inherited setter\nintercepts it).\n",{"id":3310,"difficulty":88,"q":3311,"a":3312},"end-of-chain","What is at the end of the prototype chain?","The chain ends at **`null`**. Most objects inherit from `Object.prototype`,\nwhose prototype is `null`.\n\n```js\nconst obj = {}\nObject.getPrototypeOf(obj) === Object.prototype       \u002F\u002F true\nObject.getPrototypeOf(Object.prototype) === null      \u002F\u002F true\n```\n\n`Object.prototype` provides `toString`, `hasOwnProperty`, `valueOf`, etc., which\nis why nearly every object has them. An object made with `Object.create(null)`\nhas **no** prototype, so its chain is empty.\n",{"id":3314,"difficulty":88,"q":3315,"a":3316},"methods-on-prototype","Why are methods defined on the prototype instead of each instance?","Putting methods on the prototype means **one shared copy** for all instances,\ninstead of a separate function per object — saving memory and allowing methods\nto be updated in one place.\n\n```js\nfunction User(name) { this.name = name }\nUser.prototype.greet = function () { return `Hi, ${this.name}` }\n\nconst a = new User('Ada'), b = new User('Bob')\na.greet === b.greet   \u002F\u002F true — shared method\n```\n\nEach instance holds only its own data (`name`); the behavior lives once on\n`User.prototype`. Classes do this automatically (methods go on the prototype).\n",{"id":3318,"difficulty":88,"q":3319,"a":3320},"hasownproperty","How do you tell own properties from inherited ones?","Use `hasOwnProperty` \u002F `Object.hasOwn`, which check **only own** properties,\nunlike `in` which also sees inherited ones.\n\n```js\nconst dog = Object.create({ eats: true })\ndog.barks = true\n'eats' in dog              \u002F\u002F true (inherited)\nObject.hasOwn(dog, 'eats') \u002F\u002F false (not own)\nObject.hasOwn(dog, 'barks')\u002F\u002F true\n```\n\n`Object.hasOwn` (ES2022) is the modern, robust form — it works even on\n`Object.create(null)` objects and can't be shadowed by an own property named\n`hasOwnProperty`.\n",{"id":3322,"difficulty":96,"q":3323,"a":3324},"getprototypeof","How do you get and set an object's prototype?","Use `Object.getPrototypeOf` to read and `Object.setPrototypeOf` (or\n`Object.create`) to set — prefer these over the legacy `__proto__`.\n\n```js\nconst proto = { greet() { return 'hi' } }\nconst obj = Object.create(proto)        \u002F\u002F create WITH a prototype\nObject.getPrototypeOf(obj) === proto     \u002F\u002F true\nObject.setPrototypeOf(obj, otherProto)   \u002F\u002F change it (slow — avoid in hot code)\n```\n\n`Object.setPrototypeOf` deoptimizes the object and is slow; set the prototype at\ncreation time with `Object.create` or a constructor\u002Fclass instead.\n",{"id":3326,"difficulty":88,"q":3327,"a":3328},"prototype-inheritance-vs-class","How do classes relate to prototypes?","`class` is **syntactic sugar** over prototypes. Class methods are put on the\nconstructor's `prototype`, and `extends` sets up the prototype chain — the same\nmechanism, nicer syntax.\n\n```js\nclass User {\n  constructor(name) { this.name = name }\n  greet() { return `Hi, ${this.name}` }   \u002F\u002F -> User.prototype.greet\n}\ntypeof User              \u002F\u002F 'function'\nUser.prototype.greet     \u002F\u002F the method lives here\n```\n\nUnder the hood there are no \"real\" classes — `class` desugars to constructor\nfunctions + prototype assignment, with some extras (strict mode, non-enumerable\nmethods, `new`-only invocation).\n",{"id":2289,"difficulty":88,"q":3330,"a":3331},"What is property shadowing in the prototype chain?","An **own** property with the same name as an inherited one **shadows** (hides)\nthe prototype's version — lookup stops at the own property.\n\n```js\nconst proto = { greet: () => 'from proto' }\nconst obj = Object.create(proto)\nobj.greet = () => 'from obj'\nobj.greet()  \u002F\u002F 'from obj' — shadows the prototype's greet\ndelete obj.greet\nobj.greet()  \u002F\u002F 'from proto' — inherited version reappears\n```\n\nAssigning to an inherited property creates an own one (shadowing); it doesn't\nchange the prototype. Deleting the own property reveals the inherited one again.\n",{"id":3333,"difficulty":88,"q":3334,"a":3335},"instanceof-prototype","How does instanceof use the prototype chain?","`obj instanceof Ctor` checks whether `Ctor.prototype` appears **anywhere** in\n`obj`'s prototype chain.\n\n```js\nclass Animal {}\nclass Dog extends Animal {}\nconst d = new Dog()\nd instanceof Dog     \u002F\u002F true\nd instanceof Animal  \u002F\u002F true (Animal.prototype is in the chain)\nd instanceof Object  \u002F\u002F true\n```\n\nSo it tests prototype-chain membership, not the exact constructor. It can break\nacross realms (iframes) and if you reassign `prototype`; `Symbol.hasInstance`\ncan customize its behavior.\n",{"id":3337,"difficulty":161,"q":3338,"a":3339},"constructor-property","What is the constructor property on the prototype?","Every function's `prototype` object has a `constructor` property pointing back\nto the function. Instances inherit it, so you can find the constructor that made\nan object.\n\n```js\nfunction User() {}\nUser.prototype.constructor === User   \u002F\u002F true\nconst u = new User()\nu.constructor === User                 \u002F\u002F true (inherited)\n```\n\nGotcha: if you **replace** `Prototype` entirely (`User.prototype = {...}`), you\nlose the `constructor` link unless you set it back. It's mostly informational\nand shouldn't be relied on for type checks.\n",{"id":3341,"difficulty":161,"q":3342,"a":3343},"extend-builtin","Can you add methods to built-in prototypes, and should you?","You technically can (`Array.prototype.last = function(){...}`), but you\n**shouldn't** — modifying built-in prototypes (monkey-patching) risks clashing\nwith future language features or other libraries, and breaks `for...in`.\n\n```js\n\u002F\u002F avoid — pollutes every array, may collide with a future Array.prototype\nArray.prototype.last = function () { return this[this.length - 1] }\n```\n\nPrefer standalone utility functions or subclasses. The one time it's acceptable\nis a carefully scoped **polyfill** that implements a standardized method on old\nengines.\n",{"id":3345,"difficulty":161,"q":3346,"a":3347},"prototype-pollution","What is prototype pollution?","A security vulnerability where untrusted input modifies `Object.prototype`,\naffecting **every** object in the program — often via unsafe deep-merge or\nproperty assignment using a `__proto__` key.\n\n```js\n\u002F\u002F attacker payload: { \"__proto__\": { \"isAdmin\": true } }\nmerge({}, JSON.parse(userInput))\n;({}).isAdmin   \u002F\u002F true — every object now \"has\" isAdmin\n```\n\nMitigate by rejecting `__proto__`\u002F`constructor`\u002F`prototype` keys, using\n`Object.create(null)` or `Map` for user data, and `Object.freeze(Object.\nprototype)`. It's a real-world exploit in many libraries.\n",{"id":3349,"difficulty":96,"q":3350,"a":3351},"array-prototype-methods","Where do array and string methods come from?","They live on the built-in prototypes — `Array.prototype`, `String.prototype`,\netc. — and are inherited by every array\u002Fstring via the prototype chain.\n\n```js\n[1, 2].map          === Array.prototype.map     \u002F\u002F true\n'hi'.toUpperCase    === String.prototype.toUpperCase \u002F\u002F true\n```\n\nThat's why all arrays share the same `map`\u002F`filter`. Primitives like strings are\ntemporarily **boxed** into wrapper objects so they can reach their prototype\nmethods, then discarded.\n",{"id":3353,"difficulty":161,"q":3354,"a":3355},"borrow-methods","How do you borrow methods from a prototype?","Use `call`\u002F`apply` to invoke a prototype method with a different `this` — handy\nfor array-like objects that lack array methods.\n\n```js\nfunction sum() {\n  return Array.prototype.reduce.call(arguments, (a, b) => a + b, 0)\n}\nArray.prototype.slice.call(document.querySelectorAll('div')) \u002F\u002F NodeList -> array\n```\n\nMethod borrowing leverages that prototype methods are just functions decoupled\nfrom their objects via `this`. Modern code often uses `Array.from`\u002Fspread\ninstead, but borrowing shows how the chain and `this` interact.\n",{"id":3357,"difficulty":88,"q":3358,"a":3359},"own-vs-inherited-enumeration","Do Object.keys and for...in include inherited properties?","- **`Object.keys`** — own enumerable properties only.\n- **`for...in`** — own **and inherited** enumerable properties.\n\n```js\nconst proto = { inherited: 1 }\nconst obj = Object.create(proto)\nobj.own = 2\nObject.keys(obj)            \u002F\u002F ['own']\nfor (const k in obj) console.log(k)  \u002F\u002F 'own', then 'inherited'\n```\n\nThis is why `for...in` needs a `hasOwn` guard. Built-in prototype methods are\nnon-enumerable, so they don't show up in `for...in` — only your own additions\nto prototypes would.\n",{"id":3361,"difficulty":88,"q":3362,"a":3363},"create-vs-new","What is the difference between Object.create and new?","- **`Object.create(proto)`** sets the new object's prototype to `proto` and runs\n  **no constructor**.\n- **`new Fn()`** creates an object whose prototype is `Fn.prototype`, then runs\n  `Fn` as a constructor (initializing the object).\n\n```js\nconst a = Object.create(protoObj)   \u002F\u002F prototype = protoObj, no init\nconst b = new Ctor(args)            \u002F\u002F prototype = Ctor.prototype, runs Ctor\n```\n\n`Object.create` is lower-level (just sets up the link); `new` is the full\nconstructor flow. `new Ctor()` is roughly `Object.create(Ctor.prototype)` plus\ncalling `Ctor` with the new object as `this`.\n",{"id":3365,"difficulty":161,"q":3366,"a":3367},"differential-inheritance","What is \"differential inheritance\" \u002F delegation?","JavaScript's prototype model is **delegation-based**: objects don't copy\nproperties from a \"class,\" they **delegate** missing property lookups to their\nprototype at runtime. Each object stores only what differs from its prototype.\n\n```js\nconst base = { type: 'shape', area() { return 0 } }\nconst circle = Object.create(base)\ncircle.r = 2\ncircle.area = function () { return Math.PI * this.r ** 2 } \u002F\u002F override only this\n```\n\nChanges to the prototype are immediately visible to all delegating objects (a\nlive link), unlike class-based copying. This is why the model is sometimes\ncalled \"objects linking to other objects\" (OLOO).\n",{"id":3369,"difficulty":88,"q":3370,"a":3371},"prototype-method-update","What happens if you change a prototype after instances exist?","Because the prototype link is **live**, existing instances immediately see\nchanges to their prototype.\n\n```js\nfunction User() {}\nconst u = new User()\nUser.prototype.greet = function () { return 'hi' }\nu.greet()   \u002F\u002F 'hi' — added after u was created, but visible\n```\n\nThis is a consequence of delegation: instances don't copy the prototype, they\nreference it. (Reassigning the whole `prototype` object, however, only affects\n*future* instances — existing ones keep their old prototype.)\n",{"id":3373,"difficulty":88,"q":3374,"a":3375},"typeof-vs-instanceof","When do you use typeof vs instanceof?","- **`typeof`** — for **primitives** and detecting functions (`'string'`,\n  `'number'`, `'function'`, …).\n- **`instanceof`** — for checking whether an object is built by a particular\n  constructor\u002Fclass (prototype-chain membership).\n\n```js\ntypeof 'hi'           \u002F\u002F 'string'\ntypeof []             \u002F\u002F 'object' (useless for arrays)\n[] instanceof Array   \u002F\u002F true\nnew Date instanceof Date \u002F\u002F true\n```\n\n`typeof null` is `'object'` and `typeof []` is `'object'`, so use\n`Array.isArray` for arrays and `instanceof`\u002Fduck-typing for object kinds.\n",{"id":3377,"difficulty":161,"q":3378,"a":3379},"function-prototype","Do arrow functions have a prototype property?","No. Arrow functions **lack a `prototype`** property and can't be used with\n`new`, because they're not designed to be constructors.\n\n```js\nconst arrow = () => {}\narrow.prototype          \u002F\u002F undefined\nnew arrow()              \u002F\u002F TypeError: arrow is not a constructor\n\nfunction regular() {}\nregular.prototype        \u002F\u002F {} — usable as a constructor\n```\n\nOnly regular functions (and classes) have a `prototype` object for building\ninstances. This is one of several reasons arrows are lightweight callbacks, not\ngeneral-purpose functions.\n",{"id":3381,"difficulty":161,"q":3382,"a":3383},"chain-performance","Does a long prototype chain affect performance?","Slightly — each missing-property lookup walks the chain until found or `null`,\nso very deep chains add overhead. In practice engines optimize this heavily\n(inline caches), so it rarely matters for normal depths.\n\n```js\n\u002F\u002F accessing a deeply inherited property walks more links\ndeep.someInheritedMethod()  \u002F\u002F traverses several prototypes\n```\n\nBigger wins come from not reassigning prototypes at runtime\n(`setPrototypeOf` deoptimizes) and keeping object \"shapes\" stable. Don't\nmicro-optimize chain depth; do avoid dynamic prototype mutation in hot paths.\n",{"id":3385,"difficulty":161,"q":3386,"a":3387},"mixin-prototype","How do you mix methods from multiple sources into a prototype?","Since JavaScript has single-prototype inheritance, you compose extra behavior by\n**copying methods** onto a prototype — a mixin.\n\n```js\nconst serializable = { toJSON() { return { ...this } } }\nconst loggable = { log() { console.log(this) } }\n\nclass Model {}\nObject.assign(Model.prototype, serializable, loggable)\nnew Model().log()\n```\n\n`Object.assign(Class.prototype, ...mixins)` adds shared methods without a\nsuperclass — the standard way to share behavior across unrelated classes.\n",{"id":3389,"difficulty":88,"q":3390,"a":3391},"null-prototype-pitfall","What breaks when an object has no prototype?","`Object.create(null)` objects lack `Object.prototype`, so the usual methods\n(`toString`, `hasOwnProperty`, `valueOf`) are missing.\n\n```js\nconst dict = Object.create(null)\ndict.toString()              \u002F\u002F TypeError: not a function\n`${dict}`                    \u002F\u002F throws — can't coerce to string\nObject.keys(dict)            \u002F\u002F static methods still work\ndict.hasOwnProperty          \u002F\u002F undefined -> use Object.hasOwn(dict, k)\n```\n\nUse the **static** `Object.*` methods instead of instance methods. The benefit\n(no inherited keys to collide with) is why they're used as safe maps — but a\n`Map` usually avoids these pitfalls entirely.\n",{"id":3393,"difficulty":161,"q":3394,"a":3395},"setprototypeof-vs-create","Why is Object.setPrototypeOf discouraged?","Changing an existing object's prototype forces engines to **deoptimize** it\n(its hidden class\u002Fshape changes), which is slow and can hurt every later access\nto that object.\n\n```js\n\u002F\u002F slow — mutates an existing object's prototype\nconst obj = {}\nObject.setPrototypeOf(obj, proto)\n\n\u002F\u002F fast — set the prototype at creation\nconst obj2 = Object.create(proto)\n```\n\nSet the prototype **once at creation** (`Object.create`, a class, or a\nconstructor) rather than mutating it later. MDN explicitly warns about\n`setPrototypeOf`'s performance impact.\n",{"id":3397,"difficulty":88,"q":3398,"a":3399},"prototype-vs-composition","Is prototypal inheritance better than composition?","Neither is universally better — they solve different problems. Prototypal\ninheritance shares behavior down an is-a chain; **composition** builds behavior\nby combining small, independent pieces (often favored for flexibility).\n\n```js\n\u002F\u002F composition: assemble capabilities\nconst canFly = (s) => ({ fly: () => `${s.name} flies` })\nconst bird = (name) => { const s = { name }; return { ...s, ...canFly(s) } }\n```\n\nDeep inheritance chains get rigid; composition (mixins, factory functions,\ndelegation) tends to scale better. The common guidance \"favor composition over\ninheritance\" applies in JS too.\n",{"id":3401,"difficulty":161,"q":3402,"a":3403},"getter-on-prototype","Can getters and setters live on a prototype?","Yes — accessor properties defined on a prototype are inherited and run with the\ninstance as `this`, so derived values work per instance.\n\n```js\nclass Circle {\n  constructor(r) { this.r = r }\n  get area() { return Math.PI * this.r ** 2 }  \u002F\u002F on Circle.prototype\n}\nnew Circle(2).area   \u002F\u002F 12.56... — `this` is the instance\n```\n\nClass getters\u002Fsetters live on the prototype (shared definition), but execute\nagainst each instance. You can also add them via\n`Object.defineProperty(proto, 'x', { get, set })`.\n",{"id":3405,"difficulty":161,"q":3406,"a":3407},"realm-instanceof","Why can instanceof fail across iframes or realms?","Each realm (iframe, worker, Node vm) has its **own** built-in constructors and\nprototypes. An array from another frame has a different `Array.prototype`, so\n`arr instanceof Array` is `false` in your realm.\n\n```js\nconst iframeArray = iframe.contentWindow.eval('[1, 2]')\niframeArray instanceof Array   \u002F\u002F false — different Array constructor\nArray.isArray(iframeArray)     \u002F\u002F true — realm-agnostic\n```\n\nPrefer realm-safe checks: `Array.isArray`, `Object.prototype.toString.call(x)`\n(`'[object Array]'`), or duck typing — not `instanceof` — for cross-realm code.\n",{"id":3409,"difficulty":161,"q":3410,"a":3411},"oloo","What is the OLOO pattern?","\"Objects Linking to Other Objects\" — a style (popularized by Kyle Simpson) that\nuses `Object.create` and delegation directly, without constructors, `new`, or\nclasses, embracing JavaScript's prototypal nature.\n\n```js\nconst Widget = {\n  init(w) { this.width = w; return this },\n  render() { return `width: ${this.width}` },\n}\nconst button = Object.create(Widget).init(100)\nbutton.render()  \u002F\u002F 'width: 100'\n```\n\nIt avoids the `new`\u002F`this`\u002F`prototype` ceremony and makes the delegation\nexplicit. It's a minority style — classes are more common — but it clarifies how\nprototypes actually work.\n",{"description":86},"JavaScript prototype interview questions — the prototype chain, __proto__ vs prototype, property lookup, inheritance, and how methods are shared.","javascript\u002Fobjects\u002Fprototypes-chain","Prototypes & the Prototype Chain","apN3WJNktEDjBw2n8sZQhdM5ksCiMFRiWPSCKdSPYa8",1781808672507]