[{"data":1,"prerenderedAt":4194},["ShallowReactive",2],{"page-\u002Fjs\u002F23-functional-programming":3},{"id":4,"title":5,"body":6,"description":35,"extension":4188,"meta":4189,"navigation":67,"path":4190,"seo":4191,"stem":4192,"__hash__":4193},"content\u002Fjs\u002F23-functional-programming.md","23 — Functional Programming",{"type":7,"value":8,"toc":4158},"minimark",[9,13,244,365,496,691,966,1197,1372,1552,1808,2145,2486,2615,2780,3030,3274,3448,3620,3844,3992,4154],[10,11,5],"h1",{"id":12},"_23-functional-programming",[14,15,17,27,161,201],"question-wrapper",{"language":16},"javascript",[18,19,21,22,26],"h3",{"id":20},"q1-which-function-below-is-a-pure-function","Q1. Which function below is a ",[23,24,25],"strong",{},"pure function","?",[28,29,30],"code-wrapper",{"language":16},[31,32,36],"pre",{"className":33,"code":34,"language":16,"meta":35,"style":35},"language-javascript shiki shiki-themes github-light github-dark","let taxRate = 0.08;\n\nfunction priceWithTaxA(price) {\n  return price + price * taxRate;\n}\n\nfunction priceWithTaxB(price, rate) {\n  return price + price * rate;\n}\n","",[37,38,39,62,69,89,109,115,120,140,156],"code",{"__ignoreMap":35},[40,41,44,48,52,55,59],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"svdQ7","let",[40,49,51],{"class":50},"ssxIu"," taxRate ",[40,53,54],{"class":46},"=",[40,56,58],{"class":57},"snvgF"," 0.08",[40,60,61],{"class":50},";\n",[40,63,65],{"class":42,"line":64},2,[40,66,68],{"emptyLinePlaceholder":67},true,"\n",[40,70,72,75,79,82,86],{"class":42,"line":71},3,[40,73,74],{"class":46},"function",[40,76,78],{"class":77},"sIsaT"," priceWithTaxA",[40,80,81],{"class":50},"(",[40,83,85],{"class":84},"sCrzJ","price",[40,87,88],{"class":50},") {\n",[40,90,92,95,98,101,103,106],{"class":42,"line":91},4,[40,93,94],{"class":46},"  return",[40,96,97],{"class":50}," price ",[40,99,100],{"class":46},"+",[40,102,97],{"class":50},[40,104,105],{"class":46},"*",[40,107,108],{"class":50}," taxRate;\n",[40,110,112],{"class":42,"line":111},5,[40,113,114],{"class":50},"}\n",[40,116,118],{"class":42,"line":117},6,[40,119,68],{"emptyLinePlaceholder":67},[40,121,123,125,128,130,132,135,138],{"class":42,"line":122},7,[40,124,74],{"class":46},[40,126,127],{"class":77}," priceWithTaxB",[40,129,81],{"class":50},[40,131,85],{"class":84},[40,133,134],{"class":50},", ",[40,136,137],{"class":84},"rate",[40,139,88],{"class":50},[40,141,143,145,147,149,151,153],{"class":42,"line":142},8,[40,144,94],{"class":46},[40,146,97],{"class":50},[40,148,100],{"class":46},[40,150,97],{"class":50},[40,152,105],{"class":46},[40,154,155],{"class":50}," rate;\n",[40,157,159],{"class":42,"line":158},9,[40,160,114],{"class":50},[162,163,166,180,189,195],"ul",{"className":164},[165],"contains-task-list",[167,168,171,175,176,179],"li",{"className":169},[170],"task-list-item",[172,173],"input",{"disabled":67,"type":174},"checkbox"," ",[37,177,178],{},"priceWithTaxA",", because it performs a calculation",[167,181,183,175,185,188],{"className":182},[170],[172,184],{"disabled":67,"type":174},[37,186,187],{},"priceWithTaxB",", because its output depends only on its arguments and it causes no observable side effects",[167,190,192,194],{"className":191},[170],[172,193],{"disabled":67,"type":174}," Both are pure, since neither mutates its input",[167,196,198,200],{"className":197},[170],[172,199],{"disabled":67,"type":174}," Neither is pure, since both perform arithmetic",[202,203,204,208,217],"details",{},[205,206,207],"summary",{},"Show Answer",[209,210,211,214,215,188],"p",{},[23,212,213],{},"Answer:"," B — ",[37,216,187],{},[209,218,219,222,223,227,228,230,231,234,235,237,238,240,241,243],{},[23,220,221],{},"Explanation:"," A pure function's return value must depend ",[224,225,226],"em",{},"only"," on its input parameters, with no reads of external mutable state and no side effects. ",[37,229,178],{}," reads the outer ",[37,232,233],{},"taxRate"," variable — if that variable changes between calls, the same ",[37,236,85],{}," argument produces a different result, which violates purity even though the function never mutates anything itself. ",[37,239,187],{}," closes over nothing external; every input it needs is passed explicitly, so it's deterministic and pure. This distinction matters in practice: ",[37,242,178],{}," is harder to test (you must control global state) and harder to reason about in concurrent\u002Fasync code.",[14,245,246,254,301,334],{"language":16},[18,247,249,250,253],{"id":248},"q2-why-is-the-following-function-considered-impure-beyond-just-it-uses-push","Q2. Why is the following function considered impure, beyond just \"it uses ",[37,251,252],{},"push","\"?",[28,255,256],{"language":16},[31,257,259],{"className":33,"code":258,"language":16,"meta":35,"style":35},"function addItem(cart, item) {\n  cart.push(item);\n  return cart;\n}\n",[37,260,261,280,290,297],{"__ignoreMap":35},[40,262,263,265,268,270,273,275,278],{"class":42,"line":43},[40,264,74],{"class":46},[40,266,267],{"class":77}," addItem",[40,269,81],{"class":50},[40,271,272],{"class":84},"cart",[40,274,134],{"class":50},[40,276,277],{"class":84},"item",[40,279,88],{"class":50},[40,281,282,285,287],{"class":42,"line":64},[40,283,284],{"class":50},"  cart.",[40,286,252],{"class":77},[40,288,289],{"class":50},"(item);\n",[40,291,292,294],{"class":42,"line":71},[40,293,94],{"class":46},[40,295,296],{"class":50}," cart;\n",[40,298,299],{"class":42,"line":91},[40,300,114],{"class":50},[162,302,304,310,319,325],{"className":303},[165],[167,305,307,309],{"className":306},[170],[172,308],{"disabled":67,"type":174}," It's not impure — returning a value makes any function pure",[167,311,313,315,316,318],{"className":312},[170],[172,314],{"disabled":67,"type":174}," It mutates the ",[37,317,272],{}," array argument in place, producing a side effect visible to any other code holding a reference to that same array",[167,320,322,324],{"className":321},[170],[172,323],{"disabled":67,"type":174}," It's impure only because it takes two arguments instead of one",[167,326,328,330,331,333],{"className":327},[170],[172,329],{"disabled":67,"type":174}," It's impure because ",[37,332,252],{}," is asynchronous",[202,335,336,338,345],{},[205,337,207],{},[209,339,340,342,343,318],{},[23,341,213],{}," B — It mutates the ",[37,344,272],{},[209,346,347,349,350,353,354,356,357,360,361,364],{},[23,348,221],{}," Purity isn't just about avoiding ",[224,351,352],{},"global"," state — mutating an argument that was passed in by reference (arrays and objects are reference types in JS) is itself a side effect, because any other part of the program holding a reference to that same ",[37,355,272],{}," array sees the change too, even though this function never touched a variable outside its own scope. Option A is the common misconception that \"has a return value\" automatically implies purity; a function can return something ",[224,358,359],{},"and"," still mutate its inputs, which is precisely the trap here. The pure version would return a new array: ",[37,362,363],{},"return [...cart, item]",".",[14,366,367,371,405,440],{"language":16},[18,368,370],{"id":369},"q3-what-is-the-idiomatic-immutable-way-to-add-a-property-to-an-object-without-mutating-the-original","Q3. What is the idiomatic, immutable way to add a property to an object without mutating the original?",[28,372,373],{"language":16},[31,374,376],{"className":33,"code":375,"language":16,"meta":35,"style":35},"const user = { name: \"Priya\", role: \"admin\" };\n",[37,377,378],{"__ignoreMap":35},[40,379,380,383,386,389,392,396,399,402],{"class":42,"line":43},[40,381,382],{"class":46},"const",[40,384,385],{"class":57}," user",[40,387,388],{"class":46}," =",[40,390,391],{"class":50}," { name: ",[40,393,395],{"class":394},"sJ6F3","\"Priya\"",[40,397,398],{"class":50},", role: ",[40,400,401],{"class":394},"\"admin\"",[40,403,404],{"class":50}," };\n",[162,406,408,416,424,432],{"className":407},[165],[167,409,411,175,413],{"className":410},[170],[172,412],{"disabled":67,"type":174},[37,414,415],{},"user.active = true;",[167,417,419,175,421],{"className":418},[170],[172,420],{"disabled":67,"type":174},[37,422,423],{},"Object.assign(user, { active: true });",[167,425,427,175,429],{"className":426},[170],[172,428],{"disabled":67,"type":174},[37,430,431],{},"const updated = { ...user, active: true };",[167,433,435,175,437],{"className":434},[170],[172,436],{"disabled":67,"type":174},[37,438,439],{},"user[\"active\"] = true; return user;",[202,441,442,444,451],{},[205,443,207],{},[209,445,446,448,449],{},[23,447,213],{}," C — ",[37,450,431],{},[209,452,453,455,456,459,460,463,464,467,468,470,471,473,474,477,478,481,482,484,485,488,489,491,492,495],{},[23,454,221],{}," The spread operator creates a ",[224,457,458],{},"new"," object, copying all of ",[37,461,462],{},"user","'s own enumerable properties into it and then overwriting\u002Fadding ",[37,465,466],{},"active",", leaving the original ",[37,469,462],{}," completely untouched. Options A and D directly mutate ",[37,472,462],{}," in place. Option B is the sneaky trap: ",[37,475,476],{},"Object.assign(target, source)"," mutates ",[37,479,480],{},"target"," (the first argument) — passing ",[37,483,462],{}," as the target still mutates it, even though ",[37,486,487],{},"Object.assign"," is often reached for as an \"immutable-looking\" utility; producing a new object with ",[37,490,487],{}," requires ",[37,493,494],{},"Object.assign({}, user, { active: true })",", with an empty object literal as the target.",[14,497,498,502,608,639],{"language":16},[18,499,501],{"id":500},"q4-what-does-currying-a-function-mean","Q4. What does \"currying\" a function mean?",[28,503,504],{"language":16},[31,505,507],{"className":33,"code":506,"language":16,"meta":35,"style":35},"function add(a, b, c) {\n  return a + b + c;\n}\n\nfunction curriedAdd(a) {\n  return (b) => (c) => a + b + c;\n}\n",[37,508,509,533,550,554,558,571,604],{"__ignoreMap":35},[40,510,511,513,516,518,521,523,526,528,531],{"class":42,"line":43},[40,512,74],{"class":46},[40,514,515],{"class":77}," add",[40,517,81],{"class":50},[40,519,520],{"class":84},"a",[40,522,134],{"class":50},[40,524,525],{"class":84},"b",[40,527,134],{"class":50},[40,529,530],{"class":84},"c",[40,532,88],{"class":50},[40,534,535,537,540,542,545,547],{"class":42,"line":64},[40,536,94],{"class":46},[40,538,539],{"class":50}," a ",[40,541,100],{"class":46},[40,543,544],{"class":50}," b ",[40,546,100],{"class":46},[40,548,549],{"class":50}," c;\n",[40,551,552],{"class":42,"line":71},[40,553,114],{"class":50},[40,555,556],{"class":42,"line":91},[40,557,68],{"emptyLinePlaceholder":67},[40,559,560,562,565,567,569],{"class":42,"line":111},[40,561,74],{"class":46},[40,563,564],{"class":77}," curriedAdd",[40,566,81],{"class":50},[40,568,520],{"class":84},[40,570,88],{"class":50},[40,572,573,575,578,580,583,586,588,590,592,594,596,598,600,602],{"class":42,"line":117},[40,574,94],{"class":46},[40,576,577],{"class":50}," (",[40,579,525],{"class":84},[40,581,582],{"class":50},") ",[40,584,585],{"class":46},"=>",[40,587,577],{"class":50},[40,589,530],{"class":84},[40,591,582],{"class":50},[40,593,585],{"class":46},[40,595,539],{"class":50},[40,597,100],{"class":46},[40,599,544],{"class":50},[40,601,100],{"class":46},[40,603,549],{"class":50},[40,605,606],{"class":42,"line":122},[40,607,114],{"class":50},[162,609,611,617,623,629],{"className":610},[165],[167,612,614,616],{"className":613},[170],[172,615],{"disabled":67,"type":174}," Transforming a function so it can accept its arguments one at a time, each call returning a new function until all arguments are supplied",[167,618,620,622],{"className":619},[170],[172,621],{"disabled":67,"type":174}," Making a function run faster by caching its results",[167,624,626,628],{"className":625},[170],[172,627],{"disabled":67,"type":174}," Converting a function to accept an array of arguments instead of separate parameters",[167,630,632,634,635,638],{"className":631},[170],[172,633],{"disabled":67,"type":174}," Binding a function's ",[37,636,637],{},"this"," value permanently",[202,640,641,643,648],{},[205,642,207],{},[209,644,645,647],{},[23,646,213],{}," A — Transforming a function so it can accept its arguments one at a time, each call returning a new function until all arguments are supplied",[209,649,650,175,652,655,656,658,659,662,663,655,666,668,669,672,673,676,677,679,680,683,684,687,688,690],{},[23,651,221],{},[37,653,654],{},"curriedAdd(1)"," returns a function waiting for ",[37,657,525],{},", and calling ",[224,660,661],{},"that"," with ",[37,664,665],{},"2",[37,667,530],{}," — only ",[37,670,671],{},"curriedAdd(1)(2)(3)"," produces the final sum ",[37,674,675],{},"6",". This enables partial application: ",[37,678,654],{}," can be saved and reused as a specialized function that always adds ",[37,681,682],{},"1"," to whatever comes next. Option B describes memoization, a related but distinct technique (see Q17). Option C describes a different pattern sometimes called \"argument spreading\" or using a single options object, not currying. Option D describes ",[37,685,686],{},"Function.prototype.bind","'s ",[37,689,637],{},"-binding behavior, unrelated to currying's argument-splitting purpose.",[14,692,693,701,846,910],{"language":16},[18,694,696,697,700],{"id":695},"q5-what-does-function-composition-compose-typically-achieve","Q5. What does function composition (",[37,698,699],{},"compose",") typically achieve?",[28,702,703],{"language":16},[31,704,706],{"className":33,"code":705,"language":16,"meta":35,"style":35},"const compose = (f, g) => (x) => f(g(x));\n\nconst shout = (s) => s.toUpperCase() + \"!\";\nconst exclaim = (s) => s + \"!!!\";\n\nconst shoutExclaim = compose(exclaim, shout);\nshoutExclaim(\"hello\");\n",[37,707,708,750,754,788,815,819,833],{"__ignoreMap":35},[40,709,710,712,715,717,719,722,724,727,729,731,733,736,738,740,743,745,747],{"class":42,"line":43},[40,711,382],{"class":46},[40,713,714],{"class":77}," compose",[40,716,388],{"class":46},[40,718,577],{"class":50},[40,720,721],{"class":84},"f",[40,723,134],{"class":50},[40,725,726],{"class":84},"g",[40,728,582],{"class":50},[40,730,585],{"class":46},[40,732,577],{"class":50},[40,734,735],{"class":84},"x",[40,737,582],{"class":50},[40,739,585],{"class":46},[40,741,742],{"class":77}," f",[40,744,81],{"class":50},[40,746,726],{"class":77},[40,748,749],{"class":50},"(x));\n",[40,751,752],{"class":42,"line":64},[40,753,68],{"emptyLinePlaceholder":67},[40,755,756,758,761,763,765,768,770,772,775,778,781,783,786],{"class":42,"line":71},[40,757,382],{"class":46},[40,759,760],{"class":77}," shout",[40,762,388],{"class":46},[40,764,577],{"class":50},[40,766,767],{"class":84},"s",[40,769,582],{"class":50},[40,771,585],{"class":46},[40,773,774],{"class":50}," s.",[40,776,777],{"class":77},"toUpperCase",[40,779,780],{"class":50},"() ",[40,782,100],{"class":46},[40,784,785],{"class":394}," \"!\"",[40,787,61],{"class":50},[40,789,790,792,795,797,799,801,803,805,808,810,813],{"class":42,"line":91},[40,791,382],{"class":46},[40,793,794],{"class":77}," exclaim",[40,796,388],{"class":46},[40,798,577],{"class":50},[40,800,767],{"class":84},[40,802,582],{"class":50},[40,804,585],{"class":46},[40,806,807],{"class":50}," s ",[40,809,100],{"class":46},[40,811,812],{"class":394}," \"!!!\"",[40,814,61],{"class":50},[40,816,817],{"class":42,"line":111},[40,818,68],{"emptyLinePlaceholder":67},[40,820,821,823,826,828,830],{"class":42,"line":117},[40,822,382],{"class":46},[40,824,825],{"class":57}," shoutExclaim",[40,827,388],{"class":46},[40,829,714],{"class":77},[40,831,832],{"class":50},"(exclaim, shout);\n",[40,834,835,838,840,843],{"class":42,"line":122},[40,836,837],{"class":77},"shoutExclaim",[40,839,81],{"class":50},[40,841,842],{"class":394},"\"hello\"",[40,844,845],{"class":50},");\n",[162,847,849,873,882,895],{"className":848},[165],[167,850,852,175,854,857,858,577,860,863,864,577,866,869,870,872],{"className":851},[170],[172,853],{"disabled":67,"type":174},[37,855,856],{},"\"HELLO!!!!!\""," — ",[37,859,726],{},[37,861,862],{},"shout",") runs first on the input, then ",[37,865,721],{},[37,867,868],{},"exclaim",") runs on ",[37,871,726],{},"'s result",[167,874,876,175,878,881],{"className":875},[170],[172,877],{"disabled":67,"type":174},[37,879,880],{},"\"hello!!!\""," then uppercased separately",[167,883,885,887,888,891,892,894],{"className":884},[170],[172,886],{"disabled":67,"type":174}," It throws a ",[37,889,890],{},"TypeError"," because ",[37,893,699],{}," only accepts one function",[167,896,898,175,900,577,902,904,905,577,907,909],{"className":897},[170],[172,899],{"disabled":67,"type":174},[37,901,721],{},[37,903,868],{},") runs first, then ",[37,906,726],{},[37,908,862],{},") runs on its result",[202,911,912,914,931],{},[205,913,207],{},[209,915,916,918,919,857,921,577,923,863,925,577,927,869,929,872],{},[23,917,213],{}," A — ",[37,920,856],{},[37,922,726],{},[37,924,862],{},[37,926,721],{},[37,928,868],{},[37,930,726],{},[209,932,933,935,936,939,940,943,944,947,948,951,952,955,956,951,959,961,962,965],{},[23,934,221],{}," By convention, ",[37,937,938],{},"compose(f, g)(x)"," evaluates as ",[37,941,942],{},"f(g(x))"," — the ",[224,945,946],{},"rightmost"," function runs first, and results flow right-to-left through the chain, mirroring mathematical function composition notation. Here ",[37,949,950],{},"shout(\"hello\")"," produces ",[37,953,954],{},"\"HELLO!\"",", and ",[37,957,958],{},"exclaim(\"HELLO!\")",[37,960,856],{},". This right-to-left order is a frequent point of confusion (option D reverses it), which is exactly why many functional libraries also offer a ",[37,963,964],{},"pipe"," helper that runs left-to-right instead, matching the order functions are visually listed — see Q11 for the mixup this causes.",[14,967,968,972,1117,1153],{"language":16},[18,969,971],{"id":970},"q6-which-snippet-demonstrates-point-free-tacit-style","Q6. Which snippet demonstrates \"point-free\" (tacit) style?",[28,973,974],{"language":16},[31,975,977],{"className":33,"code":976,"language":16,"meta":35,"style":35},"const names = [\"ravi\", \"priya\", \"sam\"];\n\nconst a = names.map((name) => name.toUpperCase());\nconst b = names.map(String.prototype.toUpperCase.call.bind(String.prototype.toUpperCase));\nconst c = names.map((name) => name.trim().toUpperCase());\n",[37,978,979,1007,1011,1044,1084],{"__ignoreMap":35},[40,980,981,983,986,988,991,994,996,999,1001,1004],{"class":42,"line":43},[40,982,382],{"class":46},[40,984,985],{"class":57}," names",[40,987,388],{"class":46},[40,989,990],{"class":50}," [",[40,992,993],{"class":394},"\"ravi\"",[40,995,134],{"class":50},[40,997,998],{"class":394},"\"priya\"",[40,1000,134],{"class":50},[40,1002,1003],{"class":394},"\"sam\"",[40,1005,1006],{"class":50},"];\n",[40,1008,1009],{"class":42,"line":64},[40,1010,68],{"emptyLinePlaceholder":67},[40,1012,1013,1015,1018,1020,1023,1026,1029,1032,1034,1036,1039,1041],{"class":42,"line":71},[40,1014,382],{"class":46},[40,1016,1017],{"class":57}," a",[40,1019,388],{"class":46},[40,1021,1022],{"class":50}," names.",[40,1024,1025],{"class":77},"map",[40,1027,1028],{"class":50},"((",[40,1030,1031],{"class":84},"name",[40,1033,582],{"class":50},[40,1035,585],{"class":46},[40,1037,1038],{"class":50}," name.",[40,1040,777],{"class":77},[40,1042,1043],{"class":50},"());\n",[40,1045,1046,1048,1051,1053,1055,1057,1059,1062,1064,1067,1070,1073,1075,1077,1079,1081],{"class":42,"line":91},[40,1047,382],{"class":46},[40,1049,1050],{"class":57}," b",[40,1052,388],{"class":46},[40,1054,1022],{"class":50},[40,1056,1025],{"class":77},[40,1058,81],{"class":50},[40,1060,1061],{"class":57},"String",[40,1063,364],{"class":50},[40,1065,1066],{"class":57},"prototype",[40,1068,1069],{"class":50},".toUpperCase.call.",[40,1071,1072],{"class":77},"bind",[40,1074,81],{"class":50},[40,1076,1061],{"class":57},[40,1078,364],{"class":50},[40,1080,1066],{"class":57},[40,1082,1083],{"class":50},".toUpperCase));\n",[40,1085,1086,1088,1091,1093,1095,1097,1099,1101,1103,1105,1107,1110,1113,1115],{"class":42,"line":111},[40,1087,382],{"class":46},[40,1089,1090],{"class":57}," c",[40,1092,388],{"class":46},[40,1094,1022],{"class":50},[40,1096,1025],{"class":77},[40,1098,1028],{"class":50},[40,1100,1031],{"class":84},[40,1102,582],{"class":50},[40,1104,585],{"class":46},[40,1106,1038],{"class":50},[40,1108,1109],{"class":77},"trim",[40,1111,1112],{"class":50},"().",[40,1114,777],{"class":77},[40,1116,1043],{"class":50},[162,1118,1120,1128,1139,1147],{"className":1119},[165],[167,1121,1123,175,1125,1127],{"className":1122},[170],[172,1124],{"disabled":67,"type":174},[37,1126,520],{},", because it uses an arrow function",[167,1129,1131,175,1133,1135,1136,1138],{"className":1130},[170],[172,1132],{"disabled":67,"type":174},[37,1134,525],{},", because the mapping function is referenced directly without explicitly naming or wrapping the data it operates on (no intermediate named argument like ",[37,1137,1031],{},")",[167,1140,1142,175,1144,1146],{"className":1141},[170],[172,1143],{"disabled":67,"type":174},[37,1145,530],{},", because it chains two methods",[167,1148,1150,1152],{"className":1149},[170],[172,1151],{"disabled":67,"type":174}," None of these are point-free",[202,1154,1155,1157,1165],{},[205,1156,207],{},[209,1158,1159,214,1161,1135,1163,1138],{},[23,1160,213],{},[37,1162,525],{},[37,1164,1031],{},[209,1166,1167,1169,1170,1173,1174,1176,1177,1179,1180,1182,1183,1185,1186,1189,1190,1193,1194,364],{},[23,1168,221],{}," Point-free style means defining a function without mentioning the arguments (\"points\") it operates on — you compose existing functions directly rather than writing ",[37,1171,1172],{},"(x) => f(x)",". ",[37,1175,520],{}," and ",[37,1178,530],{}," both explicitly name ",[37,1181,1031],{}," as an intermediate variable, which is the opposite of point-free. ",[37,1184,525],{}," (admittedly contrived and hard to read here, which illustrates a real trade-off) passes a function reference derived purely from existing methods, with no named parameter appearing in the mapping logic itself. In practice, simpler point-free examples look like ",[37,1187,1188],{},"names.map(s => s.toUpperCase())"," → ",[37,1191,1192],{},"names.map(String.prototype.toUpperCase.call, String.prototype)"," style tricks, or more commonly just passing a named utility function directly: ",[37,1195,1196],{},"names.map(toUpperCase)",[14,1198,1199,1203,1295,1333],{"language":16},[18,1200,1202],{"id":1201},"q7-why-is-shared-mutable-state-considered-risky-in-a-codebase-especially-with-async-code","Q7. Why is shared mutable state considered risky in a codebase, especially with async code?",[28,1204,1205],{"language":16},[31,1206,1208],{"className":33,"code":1207,"language":16,"meta":35,"style":35},"let requestCount = 0;\n\nasync function handleRequest(req) {\n  requestCount++;\n  const result = await process(req);\n  requestCount--;\n  return result;\n}\n",[37,1209,1210,1224,1228,1246,1256,1275,1284,1291],{"__ignoreMap":35},[40,1211,1212,1214,1217,1219,1222],{"class":42,"line":43},[40,1213,47],{"class":46},[40,1215,1216],{"class":50}," requestCount ",[40,1218,54],{"class":46},[40,1220,1221],{"class":57}," 0",[40,1223,61],{"class":50},[40,1225,1226],{"class":42,"line":64},[40,1227,68],{"emptyLinePlaceholder":67},[40,1229,1230,1233,1236,1239,1241,1244],{"class":42,"line":71},[40,1231,1232],{"class":46},"async",[40,1234,1235],{"class":46}," function",[40,1237,1238],{"class":77}," handleRequest",[40,1240,81],{"class":50},[40,1242,1243],{"class":84},"req",[40,1245,88],{"class":50},[40,1247,1248,1251,1254],{"class":42,"line":91},[40,1249,1250],{"class":50},"  requestCount",[40,1252,1253],{"class":46},"++",[40,1255,61],{"class":50},[40,1257,1258,1261,1264,1266,1269,1272],{"class":42,"line":111},[40,1259,1260],{"class":46},"  const",[40,1262,1263],{"class":57}," result",[40,1265,388],{"class":46},[40,1267,1268],{"class":46}," await",[40,1270,1271],{"class":77}," process",[40,1273,1274],{"class":50},"(req);\n",[40,1276,1277,1279,1282],{"class":42,"line":117},[40,1278,1250],{"class":50},[40,1280,1281],{"class":46},"--",[40,1283,61],{"class":50},[40,1285,1286,1288],{"class":42,"line":122},[40,1287,94],{"class":46},[40,1289,1290],{"class":50}," result;\n",[40,1292,1293],{"class":42,"line":142},[40,1294,114],{"class":50},[162,1296,1298,1307,1317,1325],{"className":1297},[165],[167,1299,1301,1303,1304,1306],{"className":1300},[170],[172,1302],{"disabled":67,"type":174}," It isn't risky — ",[37,1305,47],{}," variables are always safe to share",[167,1308,1310,1312,1313,1316],{"className":1309},[170],[172,1311],{"disabled":67,"type":174}," Multiple concurrent calls all read and write the same ",[37,1314,1315],{},"requestCount"," variable, so their increments\u002Fdecrements interleave in ways that are hard to trace, and any bug in one call path can corrupt state visible to every other call",[167,1318,1320,175,1322,1324],{"className":1319},[170],[172,1321],{"disabled":67,"type":174},[37,1323,1315],{}," will overflow after 2^53 requests, causing incorrect counts",[167,1326,1328,175,1330,1332],{"className":1327},[170],[172,1329],{"disabled":67,"type":174},[37,1331,1232],{}," functions cannot access variables declared outside their own body",[202,1334,1335,1337,1344],{},[205,1336,207],{},[209,1338,1339,1341,1342,1316],{},[23,1340,213],{}," B — Multiple concurrent calls all read and write the same ",[37,1343,1315],{},[209,1345,1346,1348,1349,1352,1353,1356,1357,1360,1361,1364,1365,1368,1369,1371],{},[23,1347,221],{}," Even though JavaScript is single-threaded and each individual ",[37,1350,1351],{},"requestCount++","\u002F",[37,1354,1355],{},"requestCount--"," is atomic, the ",[224,1358,1359],{},"sequence"," of operations across many concurrent ",[37,1362,1363],{},"handleRequest"," calls (each suspended and resumed at different ",[37,1366,1367],{},"await"," points) means the shared counter's value at any given moment depends on unpredictable interleaving — an early return, a thrown error skipping the decrement, or a bug in one request handler can leave ",[37,1370,1315],{}," permanently wrong for the entire process, affecting every other concurrent request. Isolating state per-call (e.g., not sharing a mutable counter at all, or using request-scoped state) avoids this entire category of bug, which is the core motivation behind functional programming's emphasis on avoiding shared mutable state.",[14,1373,1374,1382,1456,1506],{"language":16},[18,1375,1377,1378,1381],{"id":1376},"q8-objectfreeze-is-often-used-for-immutability-whats-the-gotcha-with-the-following-code","Q8. ",[37,1379,1380],{},"Object.freeze"," is often used for immutability. What's the gotcha with the following code?",[28,1383,1384],{"language":16},[31,1385,1387],{"className":33,"code":1386,"language":16,"meta":35,"style":35},"const config = Object.freeze({\n  api: { retries: 3, timeout: 5000 },\n});\n\nconfig.api.retries = 10;\nconsole.log(config.api.retries);\n",[37,1388,1389,1407,1424,1429,1433,1445],{"__ignoreMap":35},[40,1390,1391,1393,1396,1398,1401,1404],{"class":42,"line":43},[40,1392,382],{"class":46},[40,1394,1395],{"class":57}," config",[40,1397,388],{"class":46},[40,1399,1400],{"class":50}," Object.",[40,1402,1403],{"class":77},"freeze",[40,1405,1406],{"class":50},"({\n",[40,1408,1409,1412,1415,1418,1421],{"class":42,"line":64},[40,1410,1411],{"class":50},"  api: { retries: ",[40,1413,1414],{"class":57},"3",[40,1416,1417],{"class":50},", timeout: ",[40,1419,1420],{"class":57},"5000",[40,1422,1423],{"class":50}," },\n",[40,1425,1426],{"class":42,"line":71},[40,1427,1428],{"class":50},"});\n",[40,1430,1431],{"class":42,"line":91},[40,1432,68],{"emptyLinePlaceholder":67},[40,1434,1435,1438,1440,1443],{"class":42,"line":111},[40,1436,1437],{"class":50},"config.api.retries ",[40,1439,54],{"class":46},[40,1441,1442],{"class":57}," 10",[40,1444,61],{"class":50},[40,1446,1447,1450,1453],{"class":42,"line":117},[40,1448,1449],{"class":50},"console.",[40,1451,1452],{"class":77},"log",[40,1454,1455],{"class":50},"(config.api.retries);\n",[162,1457,1459,1471,1487,1498],{"className":1458},[165],[167,1460,1462,887,1464,1466,1467,1470],{"className":1461},[170],[172,1463],{"disabled":67,"type":174},[37,1465,890],{}," in strict mode because ",[37,1468,1469],{},"config"," is frozen",[167,1472,1474,1476,1477,857,1480,1482,1483,1486],{"className":1473},[170],[172,1475],{"disabled":67,"type":174}," It logs ",[37,1478,1479],{},"10",[37,1481,1380],{}," is shallow, so nested objects (",[37,1484,1485],{},"config.api",") remain fully mutable",[167,1488,1490,1476,1492,1494,1495,1497],{"className":1489},[170],[172,1491],{"disabled":67,"type":174},[37,1493,1414],{}," — the mutation silently fails because ",[37,1496,1380],{}," is deep by default",[167,1499,1501,175,1503,1505],{"className":1500},[170],[172,1502],{"disabled":67,"type":174},[37,1504,1380],{}," only works on arrays, not plain objects",[202,1507,1508,1510,1521],{},[205,1509,207],{},[209,1511,1512,1514,1515,857,1517,1482,1519,1486],{},[23,1513,213],{}," B — It logs ",[37,1516,1479],{},[37,1518,1380],{},[37,1520,1485],{},[209,1522,1523,175,1525,175,1528,1530,1531,1534,1535,1537,1538,1541,1542,1544,1545,1548,1549,1551],{},[23,1524,221],{},[23,1526,1527],{},"Safety:",[37,1529,1380],{}," only locks the ",[224,1532,1533],{},"direct"," properties of the object it's called on — it prevents reassigning ",[37,1536,1485],{}," itself to a different object, but the nested ",[37,1539,1540],{},"api"," object was never frozen, so its own properties remain fully writable. This is one of the most common ",[37,1543,1380],{}," gotchas: developers assume \"frozen\" means \"deeply immutable,\" write ",[37,1546,1547],{},"config.api.retries = 10",", and are surprised it silently succeeds (in non-strict contexts) or throws only for the ",[224,1550,1533],{}," level. Achieving true deep immutability requires recursively freezing every nested object, or using a library\u002Futility that does so.",[14,1553,1554,1562,1691,1735],{"language":16},[18,1555,1557,1558,1561],{"id":1556},"q9-what-is-the-surprising-problem-with-using-arrayprototypesort-inside-code-thats-meant-to-follow-functional-immutable-patterns","Q9. What is the surprising problem with using ",[37,1559,1560],{},"Array.prototype.sort"," inside code that's meant to follow functional, immutable patterns?",[28,1563,1564],{"language":16},[31,1565,1567],{"className":33,"code":1566,"language":16,"meta":35,"style":35},"function topScores(scores) {\n  return scores.sort((a, b) => b - a).slice(0, 3);\n}\n\nconst original = [5, 2, 9, 1, 7];\nconst top3 = topScores(original);\nconsole.log(original);\n",[37,1568,1569,1583,1627,1631,1635,1669,1683],{"__ignoreMap":35},[40,1570,1571,1573,1576,1578,1581],{"class":42,"line":43},[40,1572,74],{"class":46},[40,1574,1575],{"class":77}," topScores",[40,1577,81],{"class":50},[40,1579,1580],{"class":84},"scores",[40,1582,88],{"class":50},[40,1584,1585,1587,1590,1593,1595,1597,1599,1601,1603,1605,1607,1610,1613,1616,1618,1621,1623,1625],{"class":42,"line":64},[40,1586,94],{"class":46},[40,1588,1589],{"class":50}," scores.",[40,1591,1592],{"class":77},"sort",[40,1594,1028],{"class":50},[40,1596,520],{"class":84},[40,1598,134],{"class":50},[40,1600,525],{"class":84},[40,1602,582],{"class":50},[40,1604,585],{"class":46},[40,1606,544],{"class":50},[40,1608,1609],{"class":46},"-",[40,1611,1612],{"class":50}," a).",[40,1614,1615],{"class":77},"slice",[40,1617,81],{"class":50},[40,1619,1620],{"class":57},"0",[40,1622,134],{"class":50},[40,1624,1414],{"class":57},[40,1626,845],{"class":50},[40,1628,1629],{"class":42,"line":71},[40,1630,114],{"class":50},[40,1632,1633],{"class":42,"line":91},[40,1634,68],{"emptyLinePlaceholder":67},[40,1636,1637,1639,1642,1644,1646,1649,1651,1653,1655,1658,1660,1662,1664,1667],{"class":42,"line":111},[40,1638,382],{"class":46},[40,1640,1641],{"class":57}," original",[40,1643,388],{"class":46},[40,1645,990],{"class":50},[40,1647,1648],{"class":57},"5",[40,1650,134],{"class":50},[40,1652,665],{"class":57},[40,1654,134],{"class":50},[40,1656,1657],{"class":57},"9",[40,1659,134],{"class":50},[40,1661,682],{"class":57},[40,1663,134],{"class":50},[40,1665,1666],{"class":57},"7",[40,1668,1006],{"class":50},[40,1670,1671,1673,1676,1678,1680],{"class":42,"line":117},[40,1672,382],{"class":46},[40,1674,1675],{"class":57}," top3",[40,1677,388],{"class":46},[40,1679,1575],{"class":77},[40,1681,1682],{"class":50},"(original);\n",[40,1684,1685,1687,1689],{"class":42,"line":122},[40,1686,1449],{"class":50},[40,1688,1452],{"class":77},[40,1690,1682],{"class":50},[162,1692,1694,1706,1717,1725],{"className":1693},[165],[167,1695,1697,175,1699,1701,1702,1705],{"className":1696},[170],[172,1698],{"disabled":67,"type":174},[37,1700,1592],{}," returns a new array, so ",[37,1703,1704],{},"original"," is unaffected — this code is already pure",[167,1707,1709,175,1711,1713,1714,1716],{"className":1708},[170],[172,1710],{"disabled":67,"type":174},[37,1712,1592],{}," mutates the array in place and also returns it, so ",[37,1715,1704],{}," itself ends up reordered as a side effect, even though the function \"looks\" like it just derives a new value",[167,1718,1720,175,1722,1724],{"className":1719},[170],[172,1721],{"disabled":67,"type":174},[37,1723,1592],{}," throws an error when used with a custom comparator",[167,1726,1728,175,1730,477,1732,1734],{"className":1727},[170],[172,1729],{"disabled":67,"type":174},[37,1731,1615],{},[37,1733,1704],{}," by removing the first three elements",[202,1736,1737,1739,1747],{},[205,1738,207],{},[209,1740,1741,214,1743,1713,1745,1716],{},[23,1742,213],{},[37,1744,1592],{},[37,1746,1704],{},[209,1748,1749,175,1751,1753,1754,134,1757,134,1760,134,1763,1766,1767,1770,1771,1774,1775,1778,1779,1781,1782,1784,1785,1787,1788,1352,1790,1352,1793,1795,1796,1799,1800,1803,1804,1807],{},[23,1750,221],{},[37,1752,1560],{}," (and ",[37,1755,1756],{},"reverse",[37,1758,1759],{},"splice",[37,1761,1762],{},"fill",[37,1764,1765],{},"copyWithin",") sorts the array ",[224,1768,1769],{},"in place"," and returns the same reference — it does not create a new array. Chaining ",[37,1772,1773],{},".slice()"," afterward returns a fresh array for ",[37,1776,1777],{},"top3",", which masks the fact that ",[37,1780,1704],{}," was already silently reordered by the time ",[37,1783,1592],{}," ran. This is a classic trap for functional-style code, since ",[37,1786,1592],{}," sits right next to genuinely non-mutating array methods like ",[37,1789,1025],{},[37,1791,1792],{},"filter",[37,1794,1615],{}," and is easy to assume behaves the same way. ",[23,1797,1798],{},"Idiom:"," the fix is to copy first — ",[37,1801,1802],{},"[...scores].sort(...)"," or ",[37,1805,1806],{},"scores.toSorted(...)"," (the newer, non-mutating ES2023 method) — before sorting.",[14,1809,1810,1818,2027,2087],{"language":16},[18,1811,1813,1814,1817],{"id":1812},"q10-a-curried-function-is-built-using-functionprototypelength-to-determine-when-enough-arguments-have-been-collected-whats-the-pitfall-with-this-specific-implementation","Q10. A curried function is built using ",[37,1815,1816],{},"Function.prototype.length"," to determine when enough arguments have been collected. What's the pitfall with this specific implementation?",[28,1819,1820],{"language":16},[31,1821,1823],{"className":33,"code":1822,"language":16,"meta":35,"style":35},"function curry(fn) {\n  return function curried(...args) {\n    if (args.length >= fn.length) return fn(...args);\n    return (...more) => curried(...args, ...more);\n  };\n}\n\nfunction sum(a, b, ...rest) {\n  return a + b + rest.reduce((x, y) => x + y, 0);\n}\n\nconst curriedSum = curry(sum);\n",[37,1824,1825,1839,1858,1892,1922,1927,1931,1935,1959,2002,2007,2012],{"__ignoreMap":35},[40,1826,1827,1829,1832,1834,1837],{"class":42,"line":43},[40,1828,74],{"class":46},[40,1830,1831],{"class":77}," curry",[40,1833,81],{"class":50},[40,1835,1836],{"class":84},"fn",[40,1838,88],{"class":50},[40,1840,1841,1843,1845,1848,1850,1853,1856],{"class":42,"line":64},[40,1842,94],{"class":46},[40,1844,1235],{"class":46},[40,1846,1847],{"class":77}," curried",[40,1849,81],{"class":50},[40,1851,1852],{"class":46},"...",[40,1854,1855],{"class":84},"args",[40,1857,88],{"class":50},[40,1859,1860,1863,1866,1869,1872,1875,1877,1879,1882,1885,1887,1889],{"class":42,"line":71},[40,1861,1862],{"class":46},"    if",[40,1864,1865],{"class":50}," (args.",[40,1867,1868],{"class":57},"length",[40,1870,1871],{"class":46}," >=",[40,1873,1874],{"class":50}," fn.",[40,1876,1868],{"class":57},[40,1878,582],{"class":50},[40,1880,1881],{"class":46},"return",[40,1883,1884],{"class":77}," fn",[40,1886,81],{"class":50},[40,1888,1852],{"class":46},[40,1890,1891],{"class":50},"args);\n",[40,1893,1894,1897,1899,1901,1904,1906,1908,1910,1912,1914,1917,1919],{"class":42,"line":91},[40,1895,1896],{"class":46},"    return",[40,1898,577],{"class":50},[40,1900,1852],{"class":46},[40,1902,1903],{"class":84},"more",[40,1905,582],{"class":50},[40,1907,585],{"class":46},[40,1909,1847],{"class":77},[40,1911,81],{"class":50},[40,1913,1852],{"class":46},[40,1915,1916],{"class":50},"args, ",[40,1918,1852],{"class":46},[40,1920,1921],{"class":50},"more);\n",[40,1923,1924],{"class":42,"line":111},[40,1925,1926],{"class":50},"  };\n",[40,1928,1929],{"class":42,"line":117},[40,1930,114],{"class":50},[40,1932,1933],{"class":42,"line":122},[40,1934,68],{"emptyLinePlaceholder":67},[40,1936,1937,1939,1942,1944,1946,1948,1950,1952,1954,1957],{"class":42,"line":142},[40,1938,74],{"class":46},[40,1940,1941],{"class":77}," sum",[40,1943,81],{"class":50},[40,1945,520],{"class":84},[40,1947,134],{"class":50},[40,1949,525],{"class":84},[40,1951,134],{"class":50},[40,1953,1852],{"class":46},[40,1955,1956],{"class":84},"rest",[40,1958,88],{"class":50},[40,1960,1961,1963,1965,1967,1969,1971,1974,1977,1979,1981,1983,1986,1988,1990,1993,1995,1998,2000],{"class":42,"line":158},[40,1962,94],{"class":46},[40,1964,539],{"class":50},[40,1966,100],{"class":46},[40,1968,544],{"class":50},[40,1970,100],{"class":46},[40,1972,1973],{"class":50}," rest.",[40,1975,1976],{"class":77},"reduce",[40,1978,1028],{"class":50},[40,1980,735],{"class":84},[40,1982,134],{"class":50},[40,1984,1985],{"class":84},"y",[40,1987,582],{"class":50},[40,1989,585],{"class":46},[40,1991,1992],{"class":50}," x ",[40,1994,100],{"class":46},[40,1996,1997],{"class":50}," y, ",[40,1999,1620],{"class":57},[40,2001,845],{"class":50},[40,2003,2005],{"class":42,"line":2004},10,[40,2006,114],{"class":50},[40,2008,2010],{"class":42,"line":2009},11,[40,2011,68],{"emptyLinePlaceholder":67},[40,2013,2015,2017,2020,2022,2024],{"class":42,"line":2014},12,[40,2016,382],{"class":46},[40,2018,2019],{"class":57}," curriedSum",[40,2021,388],{"class":46},[40,2023,1831],{"class":77},[40,2025,2026],{"class":50},"(sum);\n",[162,2028,2030,2039,2064,2079],{"className":2029},[165],[167,2031,2033,2035,2036],{"className":2032},[170],[172,2034],{"disabled":67,"type":174}," It works perfectly for any function, including variadic ones like ",[37,2037,2038],{},"sum",[167,2040,2042,175,2044,2047,2048,2051,2052,857,2054,2057,2058,2060,2061,2063],{"className":2041},[170],[172,2043],{"disabled":67,"type":174},[37,2045,2046],{},"fn.length"," does not count rest parameters (or parameters after the first default-valued one), so ",[37,2049,2050],{},"sum.length"," is ",[37,2053,665],{},[37,2055,2056],{},"curriedSum"," will call ",[37,2059,2038],{}," as soon as 2 arguments arrive, silently ignoring the ability to curry in any of the ",[37,2062,1956],{}," values",[167,2065,2067,175,2069,2072,2073,2075,2076,2078],{"className":2066},[170],[172,2068],{"disabled":67,"type":174},[37,2070,2071],{},"curry"," throws a ",[37,2074,890],{}," immediately because ",[37,2077,2038],{}," uses rest parameters",[167,2080,2082,175,2084,2086],{"className":2081},[170],[172,2083],{"disabled":67,"type":174},[37,2085,2046],{}," always equals the number of arguments actually passed at call time, so this is safe",[202,2088,2089,2091,2106],{},[205,2090,207],{},[209,2092,2093,214,2095,2047,2097,2051,2099,857,2101,2057,2103,2105],{},[23,2094,213],{},[37,2096,2046],{},[37,2098,2050],{},[37,2100,665],{},[37,2102,2056],{},[37,2104,2038],{}," as soon as 2 arguments arrive, silently ignoring the ability to curry in any of the rest values",[209,2107,2108,175,2110,2112,2113,2116,2117,134,2120,2051,2122,2124,2125,2127,2128,2130,2131,2134,2135,2137,2138,2141,2142,2144],{},[23,2109,221],{},[37,2111,1816],{}," reports only the count of parameters ",[224,2114,2115],{},"before"," the first default-valued or rest parameter — it's a static count of the function's declared signature, not a runtime count of anything. For ",[37,2118,2119],{},"sum(a, b, ...rest)",[37,2121,2050],{},[37,2123,665],{},", so a ",[37,2126,1868],{},"-based ",[37,2129,2071],{}," implementation will invoke ",[37,2132,2133],{},"sum(a, b)"," the moment two arguments are collected, never giving the caller a chance to curry in additional values that ",[37,2136,1956],{}," was designed to accept. This is a real, easy-to-miss limitation of naive curry implementations, and is why production-grade curry utilities usually require an explicit arity argument (",[37,2139,2140],{},"curry(fn, arity)",") instead of trusting ",[37,2143,2046],{}," for any function that isn't a plain fixed-arity function.",[14,2146,2147,2156,2356,2363,2426],{"language":16},[18,2148,2150,2151,1176,2153,2155],{"id":2149},"q11-a-developer-mixes-up-compose-and-pipe-and-gets-an-unexpected-result-given","Q11. A developer mixes up ",[37,2152,699],{},[37,2154,964],{}," and gets an unexpected result. Given:",[28,2157,2158],{"language":16},[31,2159,2161],{"className":33,"code":2160,"language":16,"meta":35,"style":35},"const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x);\nconst pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x);\n\nconst double = (n) => n * 2;\nconst addOne = (n) => n + 1;\n\nconst a = compose(double, addOne)(5);\nconst b = pipe(double, addOne)(5);\n",[37,2162,2163,2214,2261,2265,2293,2319,2323,2340],{"__ignoreMap":35},[40,2164,2165,2167,2169,2171,2173,2175,2178,2180,2182,2184,2186,2188,2190,2193,2196,2198,2201,2203,2205,2207,2209,2211],{"class":42,"line":43},[40,2166,382],{"class":46},[40,2168,714],{"class":77},[40,2170,388],{"class":46},[40,2172,577],{"class":50},[40,2174,1852],{"class":46},[40,2176,2177],{"class":84},"fns",[40,2179,582],{"class":50},[40,2181,585],{"class":46},[40,2183,577],{"class":50},[40,2185,735],{"class":84},[40,2187,582],{"class":50},[40,2189,585],{"class":46},[40,2191,2192],{"class":50}," fns.",[40,2194,2195],{"class":77},"reduceRight",[40,2197,1028],{"class":50},[40,2199,2200],{"class":84},"acc",[40,2202,134],{"class":50},[40,2204,1836],{"class":84},[40,2206,582],{"class":50},[40,2208,585],{"class":46},[40,2210,1884],{"class":77},[40,2212,2213],{"class":50},"(acc), x);\n",[40,2215,2216,2218,2221,2223,2225,2227,2229,2231,2233,2235,2237,2239,2241,2243,2245,2247,2249,2251,2253,2255,2257,2259],{"class":42,"line":64},[40,2217,382],{"class":46},[40,2219,2220],{"class":77}," pipe",[40,2222,388],{"class":46},[40,2224,577],{"class":50},[40,2226,1852],{"class":46},[40,2228,2177],{"class":84},[40,2230,582],{"class":50},[40,2232,585],{"class":46},[40,2234,577],{"class":50},[40,2236,735],{"class":84},[40,2238,582],{"class":50},[40,2240,585],{"class":46},[40,2242,2192],{"class":50},[40,2244,1976],{"class":77},[40,2246,1028],{"class":50},[40,2248,2200],{"class":84},[40,2250,134],{"class":50},[40,2252,1836],{"class":84},[40,2254,582],{"class":50},[40,2256,585],{"class":46},[40,2258,1884],{"class":77},[40,2260,2213],{"class":50},[40,2262,2263],{"class":42,"line":71},[40,2264,68],{"emptyLinePlaceholder":67},[40,2266,2267,2269,2272,2274,2276,2279,2281,2283,2286,2288,2291],{"class":42,"line":91},[40,2268,382],{"class":46},[40,2270,2271],{"class":77}," double",[40,2273,388],{"class":46},[40,2275,577],{"class":50},[40,2277,2278],{"class":84},"n",[40,2280,582],{"class":50},[40,2282,585],{"class":46},[40,2284,2285],{"class":50}," n ",[40,2287,105],{"class":46},[40,2289,2290],{"class":57}," 2",[40,2292,61],{"class":50},[40,2294,2295,2297,2300,2302,2304,2306,2308,2310,2312,2314,2317],{"class":42,"line":111},[40,2296,382],{"class":46},[40,2298,2299],{"class":77}," addOne",[40,2301,388],{"class":46},[40,2303,577],{"class":50},[40,2305,2278],{"class":84},[40,2307,582],{"class":50},[40,2309,585],{"class":46},[40,2311,2285],{"class":50},[40,2313,100],{"class":46},[40,2315,2316],{"class":57}," 1",[40,2318,61],{"class":50},[40,2320,2321],{"class":42,"line":117},[40,2322,68],{"emptyLinePlaceholder":67},[40,2324,2325,2327,2329,2331,2333,2336,2338],{"class":42,"line":122},[40,2326,382],{"class":46},[40,2328,1017],{"class":57},[40,2330,388],{"class":46},[40,2332,714],{"class":77},[40,2334,2335],{"class":50},"(double, addOne)(",[40,2337,1648],{"class":57},[40,2339,845],{"class":50},[40,2341,2342,2344,2346,2348,2350,2352,2354],{"class":42,"line":142},[40,2343,382],{"class":46},[40,2345,1050],{"class":57},[40,2347,388],{"class":46},[40,2349,2220],{"class":77},[40,2351,2335],{"class":50},[40,2353,1648],{"class":57},[40,2355,845],{"class":50},[209,2357,2358,2359,1176,2361,26],{},"What are ",[37,2360,520],{},[37,2362,525],{},[162,2364,2366,2378,2406,2417],{"className":2365},[165],[167,2367,2369,175,2371,134,2374,2377],{"className":2368},[170],[172,2370],{"disabled":67,"type":174},[37,2372,2373],{},"a = 11",[37,2375,2376],{},"b = 11"," — order doesn't matter for these particular functions",[167,2379,2381,175,2383,134,2386,857,2388,2390,2391,2394,2395,2398,2399,2390,2401,2394,2403,2405],{"className":2380},[170],[172,2382],{"disabled":67,"type":174},[37,2384,2385],{},"a = 12",[37,2387,2376],{},[37,2389,699],{}," applies ",[37,2392,2393],{},"addOne"," first then ",[37,2396,2397],{},"double"," (right-to-left); ",[37,2400,964],{},[37,2402,2397],{},[37,2404,2393],{}," (left-to-right)",[167,2407,2409,175,2411,134,2413,2416],{"className":2408},[170],[172,2410],{"disabled":67,"type":174},[37,2412,2373],{},[37,2414,2415],{},"b = 12"," — the reverse of the above",[167,2418,2420,2422,2423,2425],{"className":2419},[170],[172,2421],{"disabled":67,"type":174}," Both throw an error because ",[37,2424,2195],{}," cannot be used with functions",[202,2427,2428,2430,2450],{},[205,2429,207],{},[209,2431,2432,214,2434,134,2436,857,2438,2390,2440,2394,2442,2398,2444,2390,2446,2394,2448,2405],{},[23,2433,213],{},[37,2435,2385],{},[37,2437,2376],{},[37,2439,699],{},[37,2441,2393],{},[37,2443,2397],{},[37,2445,964],{},[37,2447,2397],{},[37,2449,2393],{},[209,2451,2452,175,2454,2457,2458,2461,2462,2465,2466,1173,2468,2471,2472,2461,2475,2465,2478,2480,2481,1352,2483,2485],{},[23,2453,221],{},[37,2455,2456],{},"compose(double, addOne)"," runs right-to-left (per Q5): ",[37,2459,2460],{},"addOne(5) = 6",", then ",[37,2463,2464],{},"double(6) = 12",", giving ",[37,2467,2385],{},[37,2469,2470],{},"pipe(double, addOne)"," runs left-to-right: ",[37,2473,2474],{},"double(5) = 10",[37,2476,2477],{},"addOne(10) = 11",[37,2479,2376],{},". This mismatch — same function list, same input, different results purely because of which combinator was used — is exactly the gotcha that makes ",[37,2482,699],{},[37,2484,964],{}," mixups a real production bug source: swapping one for the other with the same argument order silently changes execution order rather than throwing an error, so the bug can slip past casual testing if the functions happen to be commutative for some inputs but not others.",[14,2487,2488,2492,2546,2583],{"language":16},[18,2489,2491],{"id":2490},"q12-is-the-following-function-pure","Q12. Is the following function pure?",[28,2493,2494],{"language":16},[31,2495,2497],{"className":33,"code":2496,"language":16,"meta":35,"style":35},"function createSession(userId) {\n  return { userId, createdAt: Date.now(), token: Math.random().toString(36) };\n}\n",[37,2498,2499,2513,2542],{"__ignoreMap":35},[40,2500,2501,2503,2506,2508,2511],{"class":42,"line":43},[40,2502,74],{"class":46},[40,2504,2505],{"class":77}," createSession",[40,2507,81],{"class":50},[40,2509,2510],{"class":84},"userId",[40,2512,88],{"class":50},[40,2514,2515,2517,2520,2523,2526,2529,2531,2534,2536,2539],{"class":42,"line":64},[40,2516,94],{"class":46},[40,2518,2519],{"class":50}," { userId, createdAt: Date.",[40,2521,2522],{"class":77},"now",[40,2524,2525],{"class":50},"(), token: Math.",[40,2527,2528],{"class":77},"random",[40,2530,1112],{"class":50},[40,2532,2533],{"class":77},"toString",[40,2535,81],{"class":50},[40,2537,2538],{"class":57},"36",[40,2540,2541],{"class":50},") };\n",[40,2543,2544],{"class":42,"line":71},[40,2545,114],{"class":50},[162,2547,2549,2555,2571,2577],{"className":2548},[165],[167,2550,2552,2554],{"className":2551},[170],[172,2553],{"disabled":67,"type":174}," Yes — it doesn't read or mutate any external variable",[167,2556,2558,2560,2561,1176,2564,2567,2568,2570],{"className":2557},[170],[172,2559],{"disabled":67,"type":174}," No — even though it never touches external variables, ",[37,2562,2563],{},"Date.now()",[37,2565,2566],{},"Math.random()"," make its output non-deterministic: the same ",[37,2569,2510],{}," input produces a different result on every call",[167,2572,2574,2576],{"className":2573},[170],[172,2575],{"disabled":67,"type":174}," Yes — purity only requires the absence of argument mutation, which this function satisfies",[167,2578,2580,2582],{"className":2579},[170],[172,2581],{"disabled":67,"type":174}," No — it's impure because it returns an object instead of a primitive",[202,2584,2585,2587,2598],{},[205,2586,207],{},[209,2588,2589,2591,2592,1176,2594,2567,2596,2570],{},[23,2590,213],{}," B — No — even though it never touches external variables, ",[37,2593,2563],{},[37,2595,2566],{},[37,2597,2510],{},[209,2599,2600,2602,2603,2606,2607,1176,2609,2611,2612,364],{},[23,2601,221],{}," Purity requires that calling the function with the same arguments ",[224,2604,2605],{},"always"," produces the same result — determinism is just as essential as \"no side effects.\" ",[37,2608,2563],{},[37,2610,2566],{}," both read genuinely external, constantly-changing state (the system clock, the engine's PRNG state), so even though this function never mutates anything or reads a module-level variable, it's still impure by the \"same input → same output\" definition. This is a subtle gotcha: developers often equate purity purely with \"doesn't mutate things\" (option C), missing the determinism requirement entirely. Functions needing timestamps\u002Frandomness for testability are usually made pure by accepting them as injected parameters instead: ",[37,2613,2614],{},"createSession(userId, now, randomToken)",[14,2616,2617,2624,2679,2734],{"language":16},[18,2618,2620,2621,2623],{"id":2619},"q13-whats-the-gotcha-in-this-code-given-that-const-is-often-incorrectly-equated-with-immutable","Q13. What's the gotcha in this code, given that ",[37,2622,382],{}," is often (incorrectly) equated with \"immutable\"?",[28,2625,2626],{"language":16},[31,2627,2629],{"className":33,"code":2628,"language":16,"meta":35,"style":35},"const cart = [];\ncart.push(\"item-1\");\ncart.push(\"item-2\");\nconsole.log(cart);\n",[37,2630,2631,2643,2657,2670],{"__ignoreMap":35},[40,2632,2633,2635,2638,2640],{"class":42,"line":43},[40,2634,382],{"class":46},[40,2636,2637],{"class":57}," cart",[40,2639,388],{"class":46},[40,2641,2642],{"class":50}," [];\n",[40,2644,2645,2648,2650,2652,2655],{"class":42,"line":64},[40,2646,2647],{"class":50},"cart.",[40,2649,252],{"class":77},[40,2651,81],{"class":50},[40,2653,2654],{"class":394},"\"item-1\"",[40,2656,845],{"class":50},[40,2658,2659,2661,2663,2665,2668],{"class":42,"line":71},[40,2660,2647],{"class":50},[40,2662,252],{"class":77},[40,2664,81],{"class":50},[40,2666,2667],{"class":394},"\"item-2\"",[40,2669,845],{"class":50},[40,2671,2672,2674,2676],{"class":42,"line":91},[40,2673,1449],{"class":50},[40,2675,1452],{"class":77},[40,2677,2678],{"class":50},"(cart);\n",[162,2680,2682,2695,2714,2725],{"className":2681},[165],[167,2683,2685,2687,2688,891,2690,2692,2693],{"className":2684},[170],[172,2686],{"disabled":67,"type":174}," This throws a ",[37,2689,890],{},[37,2691,272],{}," is declared ",[37,2694,382],{},[167,2696,2698,2700,2701,857,2704,2706,2707,2710,2711,2713],{"className":2697},[170],[172,2699],{"disabled":67,"type":174}," This works fine and logs ",[37,2702,2703],{},"[\"item-1\", \"item-2\"]",[37,2705,382],{}," only prevents ",[224,2708,2709],{},"reassigning"," the ",[37,2712,272],{}," binding to a different value, it does nothing to prevent mutating the object\u002Farray that binding currently points to",[167,2715,2717,175,2719,2721,2722,2724],{"className":2716},[170],[172,2718],{"disabled":67,"type":174},[37,2720,382],{}," arrays are automatically frozen, so ",[37,2723,252],{}," is a no-op",[167,2726,2728,2730,2731,2733],{"className":2727},[170],[172,2729],{"disabled":67,"type":174}," This is a syntax error since ",[37,2732,382],{}," variables cannot call methods",[202,2735,2736,2738,2750],{},[205,2737,207],{},[209,2739,2740,2742,2743,857,2745,2747,2748,2713],{},[23,2741,213],{}," B — This works fine and logs ",[37,2744,2703],{},[37,2746,382],{}," only prevents reassigning the ",[37,2749,272],{},[209,2751,2752,175,2754,2756,2757,2760,2761,2764,2765,134,2767,2770,2771,2773,2774,2776,2777,2779],{},[23,2753,221],{},[37,2755,382],{}," creates an immutable ",[224,2758,2759],{},"binding"," (you can't do ",[37,2762,2763],{},"cart = []"," again later), but it says nothing about the mutability of the value the binding refers to — arrays and objects remain fully mutable through their own methods (",[37,2766,252],{},[37,2768,2769],{},"pop",", direct property assignment) regardless of how the variable holding them was declared. This is a persistent beginner misconception (",[37,2772,382],{}," = \"constant value\") that leads to real bugs when someone assumes a ",[37,2775,382],{},"-declared array or object is safe from mutation elsewhere in the code. True immutability requires ",[37,2778,1380],{}," (with the shallow caveat from Q8) or disciplined use of non-mutating operations like spread.",[14,2781,2782,2786,2932,2994],{"language":16},[18,2783,2785],{"id":2784},"q14-what-bug-does-this-counter-factory-have-and-why","Q14. What bug does this counter factory have, and why?",[28,2787,2788],{"language":16},[31,2789,2791],{"className":33,"code":2790,"language":16,"meta":35,"style":35},"function makeCounter() {\n  let count = 0;\n  return {\n    increment: () => count++,\n    reset: () => (count = 0),\n  };\n}\n\nconst counterA = makeCounter();\nconst counterB = makeCounter();\ncounterA.increment();\ncounterA.increment();\nconsole.log(counterB.increment());\n",[37,2792,2793,2803,2817,2824,2842,2861,2865,2869,2873,2887,2900,2910,2918],{"__ignoreMap":35},[40,2794,2795,2797,2800],{"class":42,"line":43},[40,2796,74],{"class":46},[40,2798,2799],{"class":77}," makeCounter",[40,2801,2802],{"class":50},"() {\n",[40,2804,2805,2808,2811,2813,2815],{"class":42,"line":64},[40,2806,2807],{"class":46},"  let",[40,2809,2810],{"class":50}," count ",[40,2812,54],{"class":46},[40,2814,1221],{"class":57},[40,2816,61],{"class":50},[40,2818,2819,2821],{"class":42,"line":71},[40,2820,94],{"class":46},[40,2822,2823],{"class":50}," {\n",[40,2825,2826,2829,2832,2834,2837,2839],{"class":42,"line":91},[40,2827,2828],{"class":77},"    increment",[40,2830,2831],{"class":50},": () ",[40,2833,585],{"class":46},[40,2835,2836],{"class":50}," count",[40,2838,1253],{"class":46},[40,2840,2841],{"class":50},",\n",[40,2843,2844,2847,2849,2851,2854,2856,2858],{"class":42,"line":111},[40,2845,2846],{"class":77},"    reset",[40,2848,2831],{"class":50},[40,2850,585],{"class":46},[40,2852,2853],{"class":50}," (count ",[40,2855,54],{"class":46},[40,2857,1221],{"class":57},[40,2859,2860],{"class":50},"),\n",[40,2862,2863],{"class":42,"line":117},[40,2864,1926],{"class":50},[40,2866,2867],{"class":42,"line":122},[40,2868,114],{"class":50},[40,2870,2871],{"class":42,"line":142},[40,2872,68],{"emptyLinePlaceholder":67},[40,2874,2875,2877,2880,2882,2884],{"class":42,"line":158},[40,2876,382],{"class":46},[40,2878,2879],{"class":57}," counterA",[40,2881,388],{"class":46},[40,2883,2799],{"class":77},[40,2885,2886],{"class":50},"();\n",[40,2888,2889,2891,2894,2896,2898],{"class":42,"line":2004},[40,2890,382],{"class":46},[40,2892,2893],{"class":57}," counterB",[40,2895,388],{"class":46},[40,2897,2799],{"class":77},[40,2899,2886],{"class":50},[40,2901,2902,2905,2908],{"class":42,"line":2009},[40,2903,2904],{"class":50},"counterA.",[40,2906,2907],{"class":77},"increment",[40,2909,2886],{"class":50},[40,2911,2912,2914,2916],{"class":42,"line":2014},[40,2913,2904],{"class":50},[40,2915,2907],{"class":77},[40,2917,2886],{"class":50},[40,2919,2921,2923,2925,2928,2930],{"class":42,"line":2920},13,[40,2922,1449],{"class":50},[40,2924,1452],{"class":77},[40,2926,2927],{"class":50},"(counterB.",[40,2929,2907],{"class":77},[40,2931,1043],{"class":50},[162,2933,2935,2951,2968,2982],{"className":2934},[165],[167,2936,2938,175,2940,2943,2944,2946,2947,2950],{"className":2937},[170],[172,2939],{"disabled":67,"type":174},[37,2941,2942],{},"counterB.increment()"," logs ",[37,2945,665],{},", since both counters share the same closed-over ",[37,2948,2949],{},"count"," variable",[167,2952,2954,175,2956,2943,2958,2960,2961,2964,2965,2967],{"className":2953},[170],[172,2955],{"disabled":67,"type":174},[37,2957,2942],{},[37,2959,1620],{},", because each call to ",[37,2962,2963],{},"makeCounter()"," creates a fresh closure with its own independent ",[37,2966,2949],{}," variable — there's no bug here, this is correctly isolated state",[167,2969,2971,2687,2973,891,2976,2978,2979],{"className":2970},[170],[172,2972],{"disabled":67,"type":174},[37,2974,2975],{},"ReferenceError",[37,2977,2949],{}," is not accessible outside ",[37,2980,2981],{},"makeCounter",[167,2983,2985,175,2987,1176,2990,2993],{"className":2984},[170],[172,2986],{"disabled":67,"type":174},[37,2988,2989],{},"counterA",[37,2991,2992],{},"counterB"," are the same object reference, so both counters are actually identical",[202,2995,2996,2998,3010],{},[205,2997,207],{},[209,2999,3000,214,3002,2943,3004,2960,3006,2964,3008,2967],{},[23,3001,213],{},[37,3003,2942],{},[37,3005,1620],{},[37,3007,2963],{},[37,3009,2949],{},[209,3011,3012,3014,3015,3018,3019,3021,3022,3024,3025,1176,3027,3029],{},[23,3013,221],{}," This question flips the expected gotcha: many developers assume closures created from the same factory function share state (confusing this with the module-scoped shared-state problem from Q7), but each ",[224,3016,3017],{},"invocation"," of ",[37,3020,2963],{}," creates a brand-new ",[37,3023,2949],{}," variable and a brand-new pair of closures over it — ",[37,3026,2989],{},[37,3028,2992],{}," are fully independent, so incrementing one has zero effect on the other. This pattern (closures for private, per-instance state) is a deliberately safe alternative to the shared-mutable-module-variable trap from Q7, precisely because each call gets its own isolated scope rather than reading from one shared location.",[14,3031,3032,3036,3179,3230],{"language":16},[18,3033,3035],{"id":3034},"q15-which-style-is-more-idiomatic-functional-javascript-for-transforming-an-array-of-order-objects-into-a-total","Q15. Which style is more idiomatic functional JavaScript for transforming an array of order objects into a total?",[28,3037,3038],{"language":16},[31,3039,3041],{"className":33,"code":3040,"language":16,"meta":35,"style":35},"const orders = [{ amount: 20 }, { amount: 35 }, { amount: 10 }];\n\nlet totalA = 0;\nfor (let i = 0; i \u003C orders.length; i++) {\n  totalA += orders[i].amount;\n}\n\nconst totalB = orders.reduce((sum, order) => sum + order.amount, 0);\n",[37,3042,3043,3071,3075,3088,3122,3133,3137,3141],{"__ignoreMap":35},[40,3044,3045,3047,3050,3052,3055,3058,3061,3064,3066,3068],{"class":42,"line":43},[40,3046,382],{"class":46},[40,3048,3049],{"class":57}," orders",[40,3051,388],{"class":46},[40,3053,3054],{"class":50}," [{ amount: ",[40,3056,3057],{"class":57},"20",[40,3059,3060],{"class":50}," }, { amount: ",[40,3062,3063],{"class":57},"35",[40,3065,3060],{"class":50},[40,3067,1479],{"class":57},[40,3069,3070],{"class":50}," }];\n",[40,3072,3073],{"class":42,"line":64},[40,3074,68],{"emptyLinePlaceholder":67},[40,3076,3077,3079,3082,3084,3086],{"class":42,"line":71},[40,3078,47],{"class":46},[40,3080,3081],{"class":50}," totalA ",[40,3083,54],{"class":46},[40,3085,1221],{"class":57},[40,3087,61],{"class":50},[40,3089,3090,3093,3095,3097,3100,3102,3104,3107,3110,3113,3115,3118,3120],{"class":42,"line":91},[40,3091,3092],{"class":46},"for",[40,3094,577],{"class":50},[40,3096,47],{"class":46},[40,3098,3099],{"class":50}," i ",[40,3101,54],{"class":46},[40,3103,1221],{"class":57},[40,3105,3106],{"class":50},"; i ",[40,3108,3109],{"class":46},"\u003C",[40,3111,3112],{"class":50}," orders.",[40,3114,1868],{"class":57},[40,3116,3117],{"class":50},"; i",[40,3119,1253],{"class":46},[40,3121,88],{"class":50},[40,3123,3124,3127,3130],{"class":42,"line":111},[40,3125,3126],{"class":50},"  totalA ",[40,3128,3129],{"class":46},"+=",[40,3131,3132],{"class":50}," orders[i].amount;\n",[40,3134,3135],{"class":42,"line":117},[40,3136,114],{"class":50},[40,3138,3139],{"class":42,"line":122},[40,3140,68],{"emptyLinePlaceholder":67},[40,3142,3143,3145,3148,3150,3152,3154,3156,3158,3160,3163,3165,3167,3170,3172,3175,3177],{"class":42,"line":142},[40,3144,382],{"class":46},[40,3146,3147],{"class":57}," totalB",[40,3149,388],{"class":46},[40,3151,3112],{"class":50},[40,3153,1976],{"class":77},[40,3155,1028],{"class":50},[40,3157,2038],{"class":84},[40,3159,134],{"class":50},[40,3161,3162],{"class":84},"order",[40,3164,582],{"class":50},[40,3166,585],{"class":46},[40,3168,3169],{"class":50}," sum ",[40,3171,100],{"class":46},[40,3173,3174],{"class":50}," order.amount, ",[40,3176,1620],{"class":57},[40,3178,845],{"class":50},[162,3180,3182,3191,3215,3221],{"className":3181},[165],[167,3183,3185,175,3187,3190],{"className":3184},[170],[172,3186],{"disabled":67,"type":174},[37,3188,3189],{},"totalA","'s imperative loop, because it's more performant in all cases",[167,3192,3194,175,3196,687,3199,3201,3202,3205,3206,3209,3210,1352,3212,3214],{"className":3193},[170],[172,3195],{"disabled":67,"type":174},[37,3197,3198],{},"totalB",[37,3200,1976],{},", because it declares ",[224,3203,3204],{},"what"," is being computed rather than ",[224,3207,3208],{},"how"," to iterate, avoids a mutable accumulator variable in the surrounding scope, and composes naturally with ",[37,3211,1025],{},[37,3213,1792],{}," chains",[167,3216,3218,3220],{"className":3217},[170],[172,3219],{"disabled":67,"type":174}," Both are equally idiomatic; functional style has no preference here",[167,3222,3224,3226,3227],{"className":3223},[170],[172,3225],{"disabled":67,"type":174}," Neither — the idiomatic approach is ",[37,3228,3229],{},"orders.map(o => o.amount).sum()",[202,3231,3232,3234,3247],{},[205,3233,207],{},[209,3235,3236,214,3238,687,3240,3242,3243,1352,3245,3214],{},[23,3237,213],{},[37,3239,3198],{},[37,3241,1976],{},", because it declares what is being computed rather than how to iterate, avoids a mutable accumulator variable in the surrounding scope, and composes naturally with ",[37,3244,1025],{},[37,3246,1792],{},[209,3248,3249,175,3251,175,3253,3255,3256,1352,3258,3260,3261,3263,3264,3267,3268,3270,3271,3273],{},[23,3250,221],{},[23,3252,1798],{},[37,3254,1976],{}," (along with ",[37,3257,1025],{},[37,3259,1792],{},") expresses the transformation declaratively and keeps the accumulator scoped entirely inside the call rather than as a mutable ",[37,3262,47],{}," variable in the enclosing function, which reduces the surface area for bugs (accidental reuse, forgetting to reset, off-by-one loop errors) and reads closer to \"sum the amounts\" than \"manage an index and a running total.\" Option D is a tempting-looking but invalid API — plain arrays have no built-in ",[37,3265,3266],{},".sum()"," method in JavaScript. Performance (option A) is not the deciding factor here; a simple ",[37,3269,1976],{}," over a modest array is not meaningfully slower than a ",[37,3272,3092],{}," loop in practice, and clarity\u002Fcomposability is the actual reason functional style is favored for this kind of transformation.",[14,3275,3276,3280,3365,3409],{"language":16},[18,3277,3279],{"id":3278},"q16-in-a-redux-style-state-management-pattern-why-is-the-following-reducer-considered-buggy","Q16. In a Redux-style state management pattern, why is the following reducer considered buggy?",[28,3281,3282],{"language":16},[31,3283,3285],{"className":33,"code":3284,"language":16,"meta":35,"style":35},"function cartReducer(state, action) {\n  switch (action.type) {\n    case \"ADD_ITEM\":\n      state.items.push(action.item);\n      return state;\n    default:\n      return state;\n  }\n}\n",[37,3286,3287,3306,3314,3325,3335,3343,3350,3356,3361],{"__ignoreMap":35},[40,3288,3289,3291,3294,3296,3299,3301,3304],{"class":42,"line":43},[40,3290,74],{"class":46},[40,3292,3293],{"class":77}," cartReducer",[40,3295,81],{"class":50},[40,3297,3298],{"class":84},"state",[40,3300,134],{"class":50},[40,3302,3303],{"class":84},"action",[40,3305,88],{"class":50},[40,3307,3308,3311],{"class":42,"line":64},[40,3309,3310],{"class":46},"  switch",[40,3312,3313],{"class":50}," (action.type) {\n",[40,3315,3316,3319,3322],{"class":42,"line":71},[40,3317,3318],{"class":46},"    case",[40,3320,3321],{"class":394}," \"ADD_ITEM\"",[40,3323,3324],{"class":50},":\n",[40,3326,3327,3330,3332],{"class":42,"line":91},[40,3328,3329],{"class":50},"      state.items.",[40,3331,252],{"class":77},[40,3333,3334],{"class":50},"(action.item);\n",[40,3336,3337,3340],{"class":42,"line":111},[40,3338,3339],{"class":46},"      return",[40,3341,3342],{"class":50}," state;\n",[40,3344,3345,3348],{"class":42,"line":117},[40,3346,3347],{"class":46},"    default",[40,3349,3324],{"class":50},[40,3351,3352,3354],{"class":42,"line":122},[40,3353,3339],{"class":46},[40,3355,3342],{"class":50},[40,3357,3358],{"class":42,"line":142},[40,3359,3360],{"class":50},"  }\n",[40,3362,3363],{"class":42,"line":158},[40,3364,114],{"class":50},[162,3366,3368,3377,3387,3396],{"className":3367},[165],[167,3369,3371,175,3373,3376],{"className":3370},[170],[172,3372],{"disabled":67,"type":174},[37,3374,3375],{},"switch"," statements aren't allowed in reducers",[167,3378,3380,3382,3383,3386],{"className":3379},[170],[172,3381],{"disabled":67,"type":174}," It mutates ",[37,3384,3385],{},"state.items"," directly instead of returning a new state object\u002Farray, which breaks reference-equality checks that UI frameworks rely on to detect changes and re-render",[167,3388,3390,175,3392,3395],{"className":3389},[170],[172,3391],{"disabled":67,"type":174},[37,3393,3394],{},"action.item"," must be destructured before use",[167,3397,3399,3401,3402,3404,3405,3408],{"className":3398},[170],[172,3400],{"disabled":67,"type":174}," Reducers cannot return the same ",[37,3403,3298],{}," reference under any circumstance, including the ",[37,3406,3407],{},"default"," case",[202,3410,3411,3413,3420],{},[205,3412,207],{},[209,3414,3415,3417,3418,3386],{},[23,3416,213],{}," B — It mutates ",[37,3419,3385],{},[209,3421,3422,175,3424,3426,3427,3430,3431,3433,3434,3436,3437,3440,3441,3444,3445,3447],{},[23,3423,221],{},[23,3425,1798],{}," state management libraries typically detect changes with a cheap ",[37,3428,3429],{},"oldState !== newState"," reference comparison rather than a deep-equality check, for performance reasons. Mutating ",[37,3432,3385],{}," in place means ",[37,3435,3298],{}," (the object reference) never actually changes, so that comparison reports \"nothing changed\" even though the data did — this manifests as a UI that silently fails to re-render after an action that logically should have updated it. The fix follows the immutable-update pattern from Q3: ",[37,3438,3439],{},"return { ...state, items: [...state.items, action.item] }",", creating new references at every level of the update path. Option D is a false generalization — returning the ",[224,3442,3443],{},"same"," reference for ",[37,3446,3407],{}," (an unhandled\u002Fno-op action) is correct and expected, since nothing changed there.",[14,3449,3450,3454,3568,3595],{"language":16},[18,3451,3453],{"id":3452},"q17-what-performance-technique-commonly-pairs-with-pure-functions-and-why-does-purity-make-it-safe","Q17. What performance technique commonly pairs with pure functions, and why does purity make it safe?",[28,3455,3456],{"language":16},[31,3457,3459],{"className":33,"code":3458,"language":16,"meta":35,"style":35},"function memoize(fn) {\n  const cache = new Map();\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",[37,3460,3461,3474,3491,3506,3530,3543,3554,3560,3564],{"__ignoreMap":35},[40,3462,3463,3465,3468,3470,3472],{"class":42,"line":43},[40,3464,74],{"class":46},[40,3466,3467],{"class":77}," memoize",[40,3469,81],{"class":50},[40,3471,1836],{"class":84},[40,3473,88],{"class":50},[40,3475,3476,3478,3481,3483,3486,3489],{"class":42,"line":64},[40,3477,1260],{"class":46},[40,3479,3480],{"class":57}," cache",[40,3482,388],{"class":46},[40,3484,3485],{"class":46}," new",[40,3487,3488],{"class":77}," Map",[40,3490,2886],{"class":50},[40,3492,3493,3495,3497,3500,3502,3504],{"class":42,"line":71},[40,3494,94],{"class":46},[40,3496,577],{"class":50},[40,3498,3499],{"class":84},"arg",[40,3501,582],{"class":50},[40,3503,585],{"class":46},[40,3505,2823],{"class":50},[40,3507,3508,3510,3513,3516,3519,3521,3524,3527],{"class":42,"line":91},[40,3509,1862],{"class":46},[40,3511,3512],{"class":50}," (cache.",[40,3514,3515],{"class":77},"has",[40,3517,3518],{"class":50},"(arg)) ",[40,3520,1881],{"class":46},[40,3522,3523],{"class":50}," cache.",[40,3525,3526],{"class":77},"get",[40,3528,3529],{"class":50},"(arg);\n",[40,3531,3532,3535,3537,3539,3541],{"class":42,"line":111},[40,3533,3534],{"class":46},"    const",[40,3536,1263],{"class":57},[40,3538,388],{"class":46},[40,3540,1884],{"class":77},[40,3542,3529],{"class":50},[40,3544,3545,3548,3551],{"class":42,"line":117},[40,3546,3547],{"class":50},"    cache.",[40,3549,3550],{"class":77},"set",[40,3552,3553],{"class":50},"(arg, result);\n",[40,3555,3556,3558],{"class":42,"line":122},[40,3557,1896],{"class":46},[40,3559,1290],{"class":50},[40,3561,3562],{"class":42,"line":142},[40,3563,1926],{"class":50},[40,3565,3566],{"class":42,"line":158},[40,3567,114],{"class":50},[162,3569,3571,3577,3583,3589],{"className":3570},[165],[167,3572,3574,3576],{"className":3573},[170],[172,3575],{"disabled":67,"type":174}," Debouncing — pure functions are always slow, so debouncing their calls is necessary",[167,3578,3580,3582],{"className":3579},[170],[172,3581],{"disabled":67,"type":174}," Memoization — because a pure function always returns the same output for the same input, caching results by argument is safe and never returns a stale\u002Fincorrect value",[167,3584,3586,3588],{"className":3585},[170],[172,3587],{"disabled":67,"type":174}," Throttling — pure functions must be rate-limited to avoid excessive CPU use",[167,3590,3592,3594],{"className":3591},[170],[172,3593],{"disabled":67,"type":174}," Currying — memoization only works on curried functions",[202,3596,3597,3599,3604],{},[205,3598,207],{},[209,3600,3601,3603],{},[23,3602,213],{}," B — Memoization — because a pure function always returns the same output for the same input, caching results by argument is safe and never returns a stale\u002Fincorrect value",[209,3605,3606,175,3608,3611,3612,3615,3616,3619],{},[23,3607,221],{},[23,3609,3610],{},"Performance:"," memoization trades memory for time by caching a function's output keyed by its input, but this is only ",[224,3613,3614],{},"correct"," to do when the function is pure — an impure function (like the ",[37,3617,3618],{},"createSession"," example from Q12, which depends on the current time\u002Frandomness) would return a stale, wrong cached value for a later call with the same argument, since its \"true\" output legitimately changes between calls. This is why memoization utilities are typically documented as safe only for pure functions, and why introducing impurity into a previously-pure function that's already memoized somewhere is a subtle way to introduce a correctness bug.",[14,3621,3622,3626,3789,3816],{"language":16},[18,3623,3625],{"id":3624},"q18-why-do-teams-favor-composing-several-small-pure-functions-over-one-large-function-that-does-everything-from-a-testingmaintenance-standpoint","Q18. Why do teams favor composing several small pure functions over one large function that does everything, from a testing\u002Fmaintenance standpoint?",[28,3627,3628],{"language":16},[31,3629,3631],{"className":33,"code":3630,"language":16,"meta":35,"style":35},"const applyDiscount = (rate) => (price) => price - price * rate;\nconst applyTax = (rate) => (price) => price + price * rate;\nconst round2 = (price) => Math.round(price * 100) \u002F 100;\n\nconst finalPrice = (price) => round2(applyTax(0.08)(applyDiscount(0.1)(price)));\n",[37,3632,3633,3668,3703,3742,3746],{"__ignoreMap":35},[40,3634,3635,3637,3640,3642,3644,3646,3648,3650,3652,3654,3656,3658,3660,3662,3664,3666],{"class":42,"line":43},[40,3636,382],{"class":46},[40,3638,3639],{"class":77}," applyDiscount",[40,3641,388],{"class":46},[40,3643,577],{"class":50},[40,3645,137],{"class":84},[40,3647,582],{"class":50},[40,3649,585],{"class":46},[40,3651,577],{"class":50},[40,3653,85],{"class":84},[40,3655,582],{"class":50},[40,3657,585],{"class":46},[40,3659,97],{"class":50},[40,3661,1609],{"class":46},[40,3663,97],{"class":50},[40,3665,105],{"class":46},[40,3667,155],{"class":50},[40,3669,3670,3672,3675,3677,3679,3681,3683,3685,3687,3689,3691,3693,3695,3697,3699,3701],{"class":42,"line":64},[40,3671,382],{"class":46},[40,3673,3674],{"class":77}," applyTax",[40,3676,388],{"class":46},[40,3678,577],{"class":50},[40,3680,137],{"class":84},[40,3682,582],{"class":50},[40,3684,585],{"class":46},[40,3686,577],{"class":50},[40,3688,85],{"class":84},[40,3690,582],{"class":50},[40,3692,585],{"class":46},[40,3694,97],{"class":50},[40,3696,100],{"class":46},[40,3698,97],{"class":50},[40,3700,105],{"class":46},[40,3702,155],{"class":50},[40,3704,3705,3707,3710,3712,3714,3716,3718,3720,3723,3726,3729,3731,3734,3736,3738,3740],{"class":42,"line":71},[40,3706,382],{"class":46},[40,3708,3709],{"class":77}," round2",[40,3711,388],{"class":46},[40,3713,577],{"class":50},[40,3715,85],{"class":84},[40,3717,582],{"class":50},[40,3719,585],{"class":46},[40,3721,3722],{"class":50}," Math.",[40,3724,3725],{"class":77},"round",[40,3727,3728],{"class":50},"(price ",[40,3730,105],{"class":46},[40,3732,3733],{"class":57}," 100",[40,3735,582],{"class":50},[40,3737,1352],{"class":46},[40,3739,3733],{"class":57},[40,3741,61],{"class":50},[40,3743,3744],{"class":42,"line":91},[40,3745,68],{"emptyLinePlaceholder":67},[40,3747,3748,3750,3753,3755,3757,3759,3761,3763,3765,3767,3770,3772,3775,3778,3781,3783,3786],{"class":42,"line":111},[40,3749,382],{"class":46},[40,3751,3752],{"class":77}," finalPrice",[40,3754,388],{"class":46},[40,3756,577],{"class":50},[40,3758,85],{"class":84},[40,3760,582],{"class":50},[40,3762,585],{"class":46},[40,3764,3709],{"class":77},[40,3766,81],{"class":50},[40,3768,3769],{"class":77},"applyTax",[40,3771,81],{"class":50},[40,3773,3774],{"class":57},"0.08",[40,3776,3777],{"class":50},")(",[40,3779,3780],{"class":77},"applyDiscount",[40,3782,81],{"class":50},[40,3784,3785],{"class":57},"0.1",[40,3787,3788],{"class":50},")(price)));\n",[162,3790,3792,3798,3804,3810],{"className":3791},[165],[167,3793,3795,3797],{"className":3794},[170],[172,3796],{"disabled":67,"type":174}," Small functions are always faster to execute than one large function",[167,3799,3801,3803],{"className":3800},[170],[172,3802],{"disabled":67,"type":174}," Each small function can be tested and reasoned about independently with trivial input\u002Foutput assertions, and bugs are easier to isolate to a single stage of the pipeline rather than buried inside one large, tangled function",[167,3805,3807,3809],{"className":3806},[170],[172,3808],{"disabled":67,"type":174}," JavaScript engines require functions to be under a certain line count to JIT-compile them",[167,3811,3813,3815],{"className":3812},[170],[172,3814],{"disabled":67,"type":174}," Composing small functions eliminates the need for any testing at all",[202,3817,3818,3820,3825],{},[205,3819,207],{},[209,3821,3822,3824],{},[23,3823,213],{}," B — Each small function can be tested and reasoned about independently with trivial input\u002Foutput assertions, and bugs are easier to isolate to a single stage of the pipeline rather than buried inside one large, tangled function",[209,3826,3827,175,3829,3831,3832,134,3834,955,3836,3839,3840,3843],{},[23,3828,221],{},[23,3830,1798],{}," because each of ",[37,3833,3780],{},[37,3835,3769],{},[37,3837,3838],{},"round2"," is pure and does exactly one thing, each can be unit-tested with a handful of direct input\u002Foutput examples with no setup or mocking required, and if ",[37,3841,3842],{},"finalPrice"," produces a wrong result, the bug can be isolated by checking each stage's output in the pipeline rather than debugging one monolithic calculation. This composability is one of the primary practical benefits of functional style in production codebases, independent of any specific execution-speed claim (option A is a fabricated, generally false performance claim — composing functions typically has function-call overhead, not a speed benefit).",[14,3845,3846,3850,3925,3957],{"language":16},[18,3847,3849],{"id":3848},"q19-a-codebase-rewrites-this-straightforward-function-into-point-free-style-is-this-a-good-idea","Q19. A codebase rewrites this straightforward function into \"point-free\" style. Is this a good idea?",[28,3851,3852],{"language":16},[31,3853,3855],{"className":33,"code":3854,"language":16,"meta":35,"style":35},"const isAdult = (person) => person.age >= 18;\n\nconst isAdultPointFree = compose(gte(18), prop(\"age\"));\n",[37,3856,3857,3886,3890],{"__ignoreMap":35},[40,3858,3859,3861,3864,3866,3868,3871,3873,3875,3878,3881,3884],{"class":42,"line":43},[40,3860,382],{"class":46},[40,3862,3863],{"class":77}," isAdult",[40,3865,388],{"class":46},[40,3867,577],{"class":50},[40,3869,3870],{"class":84},"person",[40,3872,582],{"class":50},[40,3874,585],{"class":46},[40,3876,3877],{"class":50}," person.age ",[40,3879,3880],{"class":46},">=",[40,3882,3883],{"class":57}," 18",[40,3885,61],{"class":50},[40,3887,3888],{"class":42,"line":64},[40,3889,68],{"emptyLinePlaceholder":67},[40,3891,3892,3894,3897,3899,3901,3903,3906,3908,3911,3914,3917,3919,3922],{"class":42,"line":71},[40,3893,382],{"class":46},[40,3895,3896],{"class":57}," isAdultPointFree",[40,3898,388],{"class":46},[40,3900,714],{"class":77},[40,3902,81],{"class":50},[40,3904,3905],{"class":77},"gte",[40,3907,81],{"class":50},[40,3909,3910],{"class":57},"18",[40,3912,3913],{"class":50},"), ",[40,3915,3916],{"class":77},"prop",[40,3918,81],{"class":50},[40,3920,3921],{"class":394},"\"age\"",[40,3923,3924],{"class":50},"));\n",[162,3926,3928,3934,3945,3951],{"className":3927},[165],[167,3929,3931,3933],{"className":3930},[170],[172,3932],{"disabled":67,"type":174}," Always — point-free style is strictly superior and should be used everywhere possible",[167,3935,3937,3939,3940,1352,3942,3944],{"className":3936},[170],[172,3938],{"disabled":67,"type":174}," It depends — point-free style can be elegant for simple, well-named transformations, but overusing it (especially with unfamiliar helper functions like ",[37,3941,3905],{},[37,3943,3916],{},") can hurt readability, making code harder to scan and debug compared to a plain, explicit arrow function",[167,3946,3948,3950],{"className":3947},[170],[172,3949],{"disabled":67,"type":174}," Never — point-free style is always harder to read than named-parameter style",[167,3952,3954,3956],{"className":3953},[170],[172,3955],{"disabled":67,"type":174}," It doesn't matter — both versions are byte-for-byte identical after minification, so there's no practical difference",[202,3958,3959,3961,3970],{},[205,3960,207],{},[209,3962,3963,3965,3966,1352,3968,3944],{},[23,3964,213],{}," B — It depends — point-free style can be elegant for simple, well-named transformations, but overusing it (especially with unfamiliar helper functions like ",[37,3967,3905],{},[37,3969,3916],{},[209,3971,3972,175,3974,3976,3977,134,3979,3982,3983,134,3985,3987,3988,3991],{},[23,3973,221],{},[23,3975,1798],{}," point-free style trades an explicit, named parameter (",[37,3978,3870],{},[37,3980,3981],{},"person.age",") for implicit data flow through composed helper functions — readable to someone fluent in the specific utility library's vocabulary (",[37,3984,3905],{},[37,3986,3916],{}," are common in libraries like Ramda), but opaque to someone who isn't, and notably harder to debug since there's no intermediate named value to inspect in a debugger or log statement. The original ",[37,3989,3990],{},"isAdult"," is immediately clear to any JavaScript developer regardless of functional-programming background. Neither extreme (option A \"always\" or option C \"never\") reflects real engineering judgment — the right call depends on team familiarity, the complexity of the transformation, and whether the point-free version actually reads more clearly than the explicit one.",[14,3993,3994,3998,4066,4110],{"language":16},[18,3995,3997],{"id":3996},"q20-a-module-exports-a-shared-configuration-object-that-multiple-other-modules-import-and-occasionally-mutate-directly-what-is-the-idiomatic-functional-programming-fix-for-this-shared-mutable-state-hazard","Q20. A module exports a shared configuration object that multiple other modules import and occasionally mutate directly. What is the idiomatic functional-programming fix for this shared-mutable-state hazard?",[28,3999,4000],{"language":16},[31,4001,4003],{"className":33,"code":4002,"language":16,"meta":35,"style":35},"export const appConfig = { retries: 3, timeout: 5000 };\n\n\u002F\u002F elsewhere, in an unrelated module:\nimport { appConfig } from \".\u002Fconfig.js\";\nappConfig.retries = 10;\n",[37,4004,4005,4029,4033,4039,4055],{"__ignoreMap":35},[40,4006,4007,4010,4013,4016,4018,4021,4023,4025,4027],{"class":42,"line":43},[40,4008,4009],{"class":46},"export",[40,4011,4012],{"class":46}," const",[40,4014,4015],{"class":57}," appConfig",[40,4017,388],{"class":46},[40,4019,4020],{"class":50}," { retries: ",[40,4022,1414],{"class":57},[40,4024,1417],{"class":50},[40,4026,1420],{"class":57},[40,4028,404],{"class":50},[40,4030,4031],{"class":42,"line":64},[40,4032,68],{"emptyLinePlaceholder":67},[40,4034,4035],{"class":42,"line":71},[40,4036,4038],{"class":4037},"sdCPZ","\u002F\u002F elsewhere, in an unrelated module:\n",[40,4040,4041,4044,4047,4050,4053],{"class":42,"line":91},[40,4042,4043],{"class":46},"import",[40,4045,4046],{"class":50}," { appConfig } ",[40,4048,4049],{"class":46},"from",[40,4051,4052],{"class":394}," \".\u002Fconfig.js\"",[40,4054,61],{"class":50},[40,4056,4057,4060,4062,4064],{"class":42,"line":111},[40,4058,4059],{"class":50},"appConfig.retries ",[40,4061,54],{"class":46},[40,4063,1442],{"class":57},[40,4065,61],{"class":50},[162,4067,4069,4075,4088,4101],{"className":4068},[165],[167,4070,4072,4074],{"className":4071},[170],[172,4073],{"disabled":67,"type":174}," Nothing needs to change — ES module bindings are read-only by default, so this mutation already fails silently",[167,4076,4078,4080,4081,4083,4084,4087],{"className":4077},[170],[172,4079],{"disabled":67,"type":174}," Freeze the exported object with ",[37,4082,1380],{}," (deeply, if it has nested data) so accidental mutation throws (in strict mode) or silently no-ops instead of corrupting shared state, and provide an explicit function like ",[37,4085,4086],{},"updateConfig(patch)"," that returns a new merged object for legitimate updates",[167,4089,4091,4093,4094,4097,4098,4100],{"className":4090},[170],[172,4092],{"disabled":67,"type":174}," Export a ",[37,4095,4096],{},"let appConfig"," instead of ",[37,4099,382],{}," so reassignment is explicitly allowed",[167,4102,4104,4106,4107],{"className":4103},[170],[172,4105],{"disabled":67,"type":174}," Wrap every property access across the codebase in a ",[37,4108,4109],{},"try\u002Fcatch",[202,4111,4112,4114,4123],{},[205,4113,207],{},[209,4115,4116,4118,4119,4083,4121,4087],{},[23,4117,213],{}," B — Freeze the exported object with ",[37,4120,1380],{},[37,4122,4086],{},[209,4124,4125,175,4127,4129,4130,577,4133,4136,4137,4139,4140,4143,4144,4146,4147,4149,4150,4153],{},[23,4126,221],{},[23,4128,1798],{}," ES module bindings only make the ",[224,4131,4132],{},"binding itself",[37,4134,4135],{},"appConfig"," as a name) immutable from an importing module's perspective — you can't reassign what ",[37,4138,4135],{}," refers to from outside the exporting module — but that says nothing about mutating the ",[224,4141,4142],{},"object's properties",", which remain fully writable by default (option A's premise is false, echoing the ",[37,4145,382],{}," gotcha from Q13, just at module scope instead of function scope). ",[37,4148,1380],{}," closes that hole directly, and pairing it with an explicit, controlled update function keeps all legitimate state changes traceable to one place instead of scattered ",[37,4151,4152],{},"appConfig.x = y"," mutations anywhere in the codebase, directly addressing the shared-mutable-state risk described in Q7.",[4155,4156,4157],"style",{},"html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}",{"title":35,"searchDepth":64,"depth":64,"links":4159},[4160,4162,4164,4165,4166,4168,4169,4170,4172,4174,4176,4178,4179,4181,4182,4183,4184,4185,4186,4187],{"id":20,"depth":71,"text":4161},"Q1. Which function below is a pure function?",{"id":248,"depth":71,"text":4163},"Q2. Why is the following function considered impure, beyond just \"it uses push\"?",{"id":369,"depth":71,"text":370},{"id":500,"depth":71,"text":501},{"id":695,"depth":71,"text":4167},"Q5. What does function composition (compose) typically achieve?",{"id":970,"depth":71,"text":971},{"id":1201,"depth":71,"text":1202},{"id":1376,"depth":71,"text":4171},"Q8. Object.freeze is often used for immutability. What's the gotcha with the following code?",{"id":1556,"depth":71,"text":4173},"Q9. What is the surprising problem with using Array.prototype.sort inside code that's meant to follow functional, immutable patterns?",{"id":1812,"depth":71,"text":4175},"Q10. A curried function is built using Function.prototype.length to determine when enough arguments have been collected. What's the pitfall with this specific implementation?",{"id":2149,"depth":71,"text":4177},"Q11. A developer mixes up compose and pipe and gets an unexpected result. Given:",{"id":2490,"depth":71,"text":2491},{"id":2619,"depth":71,"text":4180},"Q13. What's the gotcha in this code, given that const is often (incorrectly) equated with \"immutable\"?",{"id":2784,"depth":71,"text":2785},{"id":3034,"depth":71,"text":3035},{"id":3278,"depth":71,"text":3279},{"id":3452,"depth":71,"text":3453},{"id":3624,"depth":71,"text":3625},{"id":3848,"depth":71,"text":3849},{"id":3996,"depth":71,"text":3997},"md",{},"\u002Fjs\u002F23-functional-programming",{"title":5,"description":35},"js\u002F23-functional-programming","D_d2ER0Vy-RW0lgiZRfgf0xhA5dpWOgjaCJPB7jxMBI",1787335397336]