[{"data":1,"prerenderedAt":1425},["ShallowReactive",2],{"blog-\u002Fblog\u002Fjavascript-higher-order-functions":3},{"id":4,"title":5,"body":6,"description":1410,"difficulty":1411,"extension":1412,"framework":1413,"frameworkSlug":1414,"meta":1415,"navigation":280,"order":168,"path":1416,"qaPath":1417,"seo":1418,"stem":1419,"subtopic":1420,"topic":1421,"topicSlug":1422,"updated":1423,"__hash__":1424},"blog\u002Fblog\u002Fjavascript-higher-order-functions.md","JavaScript Higher-Order Functions — Currying, Composition, Memoization and More",{"type":7,"value":8,"toc":1397},"minimark",[9,14,44,48,55,187,208,212,223,353,364,368,374,586,598,602,607,729,736,740,753,845,852,856,861,1068,1079,1083,1094,1218,1221,1225,1228,1326,1332,1336,1347,1351,1390,1393],[10,11,13],"h2",{"id":12},"functions-as-values","Functions as values",[15,16,17,18,22,23,26,27,31,32,36,37,40,41,43],"p",{},"JavaScript treats functions as ",[19,20,21],"strong",{},"first-class values",": you can store them in variables, pass\nthem as arguments, and return them from other functions. A ",[19,24,25],{},"higher-order function"," (HOF) is\nany function that does the latter two — it takes a function as an argument, returns a function\nas a result, or both. This single capability underpins a huge amount of idiomatic JavaScript:\narray methods, event handling, functional composition, and patterns like memoization and\ndebouncing. Understanding HOFs deeply turns you from someone who ",[28,29,30],"em",{},"uses"," ",[33,34,35],"code",{},"map"," into someone who\ncan ",[28,38,39],{},"build"," the next ",[33,42,35],{},".",[10,45,47],{"id":46},"callbacks-passing-functions-in","Callbacks: passing functions in",[15,49,50,51,54],{},"The simplest HOFs accept a function to call — a ",[19,52,53],{},"callback",". The array iteration methods are\nthe canonical example.",[56,57,62],"pre",{"className":58,"code":59,"language":60,"meta":61,"style":61},"language-js shiki shiki-themes github-light github-dark","[1, 2, 3].map(n => n * 2)              \u002F\u002F map takes a function\n[1, 2, 3].filter(n => n % 2 === 1)     \u002F\u002F so does filter\nbutton.addEventListener('click', handleClick)   \u002F\u002F and event APIs\n","js","",[33,63,64,121,166],{"__ignoreMap":61},[65,66,69,73,77,80,83,85,88,91,94,97,101,105,108,111,114,117],"span",{"class":67,"line":68},"line",1,[65,70,72],{"class":71},"sVt8B","[",[65,74,76],{"class":75},"sj4cs","1",[65,78,79],{"class":71},", ",[65,81,82],{"class":75},"2",[65,84,79],{"class":71},[65,86,87],{"class":75},"3",[65,89,90],{"class":71},"].",[65,92,35],{"class":93},"sScJk",[65,95,96],{"class":71},"(",[65,98,100],{"class":99},"s4XuR","n",[65,102,104],{"class":103},"szBVR"," =>",[65,106,107],{"class":71}," n ",[65,109,110],{"class":103},"*",[65,112,113],{"class":75}," 2",[65,115,116],{"class":71},")              ",[65,118,120],{"class":119},"sJ8bj","\u002F\u002F map takes a function\n",[65,122,124,126,128,130,132,134,136,138,141,143,145,147,149,152,154,157,160,163],{"class":67,"line":123},2,[65,125,72],{"class":71},[65,127,76],{"class":75},[65,129,79],{"class":71},[65,131,82],{"class":75},[65,133,79],{"class":71},[65,135,87],{"class":75},[65,137,90],{"class":71},[65,139,140],{"class":93},"filter",[65,142,96],{"class":71},[65,144,100],{"class":99},[65,146,104],{"class":103},[65,148,107],{"class":71},[65,150,151],{"class":103},"%",[65,153,113],{"class":75},[65,155,156],{"class":103}," ===",[65,158,159],{"class":75}," 1",[65,161,162],{"class":71},")     ",[65,164,165],{"class":119},"\u002F\u002F so does filter\n",[65,167,169,172,175,177,181,184],{"class":67,"line":168},3,[65,170,171],{"class":71},"button.",[65,173,174],{"class":93},"addEventListener",[65,176,96],{"class":71},[65,178,180],{"class":179},"sZZnC","'click'",[65,182,183],{"class":71},", handleClick)   ",[65,185,186],{"class":119},"\u002F\u002F and event APIs\n",[15,188,189,190,192,193,196,197,200,201,204,205,43],{},"Passing behavior as data is what makes these methods reusable: ",[33,191,35],{}," doesn't know or care what\ntransformation you want — you supply it. A common pitfall is passing a method reference and\nlosing ",[33,194,195],{},"this",", or the famous ",[33,198,199],{},"['1','2','3'].map(parseInt)"," trap (where ",[33,202,203],{},"parseInt"," receives the\nindex as its radix argument). Wrap in an explicit arrow when in doubt:\n",[33,206,207],{},".map(s => parseInt(s, 10))",[10,209,211],{"id":210},"returning-functions","Returning functions",[15,213,214,215,218,219,222],{},"HOFs that ",[19,216,217],{},"return"," functions let you build specialized functions on the fly. A ",[28,220,221],{},"function\nfactory"," captures configuration in a closure and returns a tailored function.",[56,224,226],{"className":58,"code":225,"language":60,"meta":61,"style":61},"function multiplier(factor) {\n  return (n) => n * factor          \u002F\u002F returned function closes over `factor`\n}\n\nconst double = multiplier(2)\nconst triple = multiplier(3)\ndouble(5)   \u002F\u002F 10\ntriple(5)   \u002F\u002F 15\n",[33,227,228,244,270,275,282,303,321,338],{"__ignoreMap":61},[65,229,230,233,236,238,241],{"class":67,"line":68},[65,231,232],{"class":103},"function",[65,234,235],{"class":93}," multiplier",[65,237,96],{"class":71},[65,239,240],{"class":99},"factor",[65,242,243],{"class":71},") {\n",[65,245,246,249,252,254,257,260,262,264,267],{"class":67,"line":123},[65,247,248],{"class":103},"  return",[65,250,251],{"class":71}," (",[65,253,100],{"class":99},[65,255,256],{"class":71},") ",[65,258,259],{"class":103},"=>",[65,261,107],{"class":71},[65,263,110],{"class":103},[65,265,266],{"class":71}," factor          ",[65,268,269],{"class":119},"\u002F\u002F returned function closes over `factor`\n",[65,271,272],{"class":67,"line":168},[65,273,274],{"class":71},"}\n",[65,276,278],{"class":67,"line":277},4,[65,279,281],{"emptyLinePlaceholder":280},true,"\n",[65,283,285,288,291,294,296,298,300],{"class":67,"line":284},5,[65,286,287],{"class":103},"const",[65,289,290],{"class":75}," double",[65,292,293],{"class":103}," =",[65,295,235],{"class":93},[65,297,96],{"class":71},[65,299,82],{"class":75},[65,301,302],{"class":71},")\n",[65,304,306,308,311,313,315,317,319],{"class":67,"line":305},6,[65,307,287],{"class":103},[65,309,310],{"class":75}," triple",[65,312,293],{"class":103},[65,314,235],{"class":93},[65,316,96],{"class":71},[65,318,87],{"class":75},[65,320,302],{"class":71},[65,322,324,327,329,332,335],{"class":67,"line":323},7,[65,325,326],{"class":93},"double",[65,328,96],{"class":71},[65,330,331],{"class":75},"5",[65,333,334],{"class":71},")   ",[65,336,337],{"class":119},"\u002F\u002F 10\n",[65,339,341,344,346,348,350],{"class":67,"line":340},8,[65,342,343],{"class":93},"triple",[65,345,96],{"class":71},[65,347,331],{"class":75},[65,349,334],{"class":71},[65,351,352],{"class":119},"\u002F\u002F 15\n",[15,354,355,357,358,360,361,363],{},[33,356,326],{}," and ",[33,359,343],{}," are distinct functions, each remembering its own ",[33,362,240],{},". This is the\nfoundation of currying and partial application.",[10,365,367],{"id":366},"function-composition","Function composition",[15,369,370,373],{},[19,371,372],{},"Composition"," combines small functions into a pipeline where each function's output feeds\nthe next. It's the functional-programming way to build complex transformations from simple,\ntestable pieces.",[56,375,377],{"className":58,"code":376,"language":60,"meta":61,"style":61},"const 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(\n  s => s.trim(),\n  s => s.toLowerCase(),\n  s => s.replace(\u002F\\s+\u002Fg, '-')\n)\nclean('  Hello World  ')   \u002F\u002F 'hello-world'\n",[33,378,379,436,485,489,503,519,532,566,570],{"__ignoreMap":61},[65,380,381,383,386,388,390,393,396,398,400,402,405,407,409,412,415,418,421,423,426,428,430,433],{"class":67,"line":68},[65,382,287],{"class":103},[65,384,385],{"class":93}," compose",[65,387,293],{"class":103},[65,389,251],{"class":71},[65,391,392],{"class":103},"...",[65,394,395],{"class":99},"fns",[65,397,256],{"class":71},[65,399,259],{"class":103},[65,401,251],{"class":71},[65,403,404],{"class":99},"x",[65,406,256],{"class":71},[65,408,259],{"class":103},[65,410,411],{"class":71}," fns.",[65,413,414],{"class":93},"reduceRight",[65,416,417],{"class":71},"((",[65,419,420],{"class":99},"acc",[65,422,79],{"class":71},[65,424,425],{"class":99},"fn",[65,427,256],{"class":71},[65,429,259],{"class":103},[65,431,432],{"class":93}," fn",[65,434,435],{"class":71},"(acc), x)\n",[65,437,438,440,443,446,448,450,452,454,456,458,460,462,464,466,469,471,473,475,477,479,481,483],{"class":67,"line":123},[65,439,287],{"class":103},[65,441,442],{"class":93}," pipe",[65,444,445],{"class":103},"    =",[65,447,251],{"class":71},[65,449,392],{"class":103},[65,451,395],{"class":99},[65,453,256],{"class":71},[65,455,259],{"class":103},[65,457,251],{"class":71},[65,459,404],{"class":99},[65,461,256],{"class":71},[65,463,259],{"class":103},[65,465,411],{"class":71},[65,467,468],{"class":93},"reduce",[65,470,417],{"class":71},[65,472,420],{"class":99},[65,474,79],{"class":71},[65,476,425],{"class":99},[65,478,256],{"class":71},[65,480,259],{"class":103},[65,482,432],{"class":93},[65,484,435],{"class":71},[65,486,487],{"class":67,"line":168},[65,488,281],{"emptyLinePlaceholder":280},[65,490,491,493,496,498,500],{"class":67,"line":277},[65,492,287],{"class":103},[65,494,495],{"class":75}," clean",[65,497,293],{"class":103},[65,499,442],{"class":93},[65,501,502],{"class":71},"(\n",[65,504,505,508,510,513,516],{"class":67,"line":284},[65,506,507],{"class":99},"  s",[65,509,104],{"class":103},[65,511,512],{"class":71}," s.",[65,514,515],{"class":93},"trim",[65,517,518],{"class":71},"(),\n",[65,520,521,523,525,527,530],{"class":67,"line":305},[65,522,507],{"class":99},[65,524,104],{"class":103},[65,526,512],{"class":71},[65,528,529],{"class":93},"toLowerCase",[65,531,518],{"class":71},[65,533,534,536,538,540,543,545,548,551,554,556,559,561,564],{"class":67,"line":323},[65,535,507],{"class":99},[65,537,104],{"class":103},[65,539,512],{"class":71},[65,541,542],{"class":93},"replace",[65,544,96],{"class":71},[65,546,547],{"class":179},"\u002F",[65,549,550],{"class":75},"\\s",[65,552,553],{"class":103},"+",[65,555,547],{"class":179},[65,557,558],{"class":103},"g",[65,560,79],{"class":71},[65,562,563],{"class":179},"'-'",[65,565,302],{"class":71},[65,567,568],{"class":67,"line":340},[65,569,302],{"class":71},[65,571,573,576,578,581,583],{"class":67,"line":572},9,[65,574,575],{"class":93},"clean",[65,577,96],{"class":71},[65,579,580],{"class":179},"'  Hello World  '",[65,582,334],{"class":71},[65,584,585],{"class":119},"\u002F\u002F 'hello-world'\n",[15,587,588,591,592,595,596,43],{},[33,589,590],{},"pipe"," reads left-to-right (the order data flows); ",[33,593,594],{},"compose"," reads right-to-left (the\nmathematical convention). Both are tiny HOFs built on ",[33,597,468],{},[10,599,601],{"id":600},"currying","Currying",[15,603,604,606],{},[19,605,601],{}," transforms a multi-argument function into a chain of single-argument functions.\nIt enables maximum reuse and partial specialization.",[56,608,610],{"className":58,"code":609,"language":60,"meta":61,"style":61},"const add = (a) => (b) => (c) => a + b + c\nadd(1)(2)(3)   \u002F\u002F 6\n\nconst add10 = add(10)       \u002F\u002F partially applied\nadd10(5)(2)    \u002F\u002F 17\n",[33,611,612,661,684,688,710],{"__ignoreMap":61},[65,613,614,616,619,621,623,626,628,630,632,635,637,639,641,644,646,648,651,653,656,658],{"class":67,"line":68},[65,615,287],{"class":103},[65,617,618],{"class":93}," add",[65,620,293],{"class":103},[65,622,251],{"class":71},[65,624,625],{"class":99},"a",[65,627,256],{"class":71},[65,629,259],{"class":103},[65,631,251],{"class":71},[65,633,634],{"class":99},"b",[65,636,256],{"class":71},[65,638,259],{"class":103},[65,640,251],{"class":71},[65,642,643],{"class":99},"c",[65,645,256],{"class":71},[65,647,259],{"class":103},[65,649,650],{"class":71}," a ",[65,652,553],{"class":103},[65,654,655],{"class":71}," b ",[65,657,553],{"class":103},[65,659,660],{"class":71}," c\n",[65,662,663,666,668,670,673,675,677,679,681],{"class":67,"line":123},[65,664,665],{"class":93},"add",[65,667,96],{"class":71},[65,669,76],{"class":75},[65,671,672],{"class":71},")(",[65,674,82],{"class":75},[65,676,672],{"class":71},[65,678,87],{"class":75},[65,680,334],{"class":71},[65,682,683],{"class":119},"\u002F\u002F 6\n",[65,685,686],{"class":67,"line":168},[65,687,281],{"emptyLinePlaceholder":280},[65,689,690,692,695,697,699,701,704,707],{"class":67,"line":277},[65,691,287],{"class":103},[65,693,694],{"class":75}," add10",[65,696,293],{"class":103},[65,698,618],{"class":93},[65,700,96],{"class":71},[65,702,703],{"class":75},"10",[65,705,706],{"class":71},")       ",[65,708,709],{"class":119},"\u002F\u002F partially applied\n",[65,711,712,715,717,719,721,723,726],{"class":67,"line":284},[65,713,714],{"class":93},"add10",[65,716,96],{"class":71},[65,718,331],{"class":75},[65,720,672],{"class":71},[65,722,82],{"class":75},[65,724,725],{"class":71},")    ",[65,727,728],{"class":119},"\u002F\u002F 17\n",[15,730,731,732,547,734,43],{},"Each call returns a function awaiting the next argument until all are supplied. Curried\nfunctions compose beautifully because they're naturally unary (one argument), fitting straight\ninto ",[33,733,590],{},[33,735,594],{},[10,737,739],{"id":738},"partial-application","Partial application",[15,741,742,744,745,748,749,752],{},[19,743,739],{}," fixes ",[28,746,747],{},"some"," of a function's arguments, producing a new function that\ntakes the rest. It's subtly different from currying (which fixes one at a time) but serves a\nsimilar goal. ",[33,750,751],{},"Function.prototype.bind"," does partial application built-in.",[56,754,756],{"className":58,"code":755,"language":60,"meta":61,"style":61},"function greet(greeting, name) { return `${greeting}, ${name}!` }\n\nconst sayHello = greet.bind(null, 'Hello')   \u002F\u002F fix the greeting\nsayHello('Ada')   \u002F\u002F 'Hello, Ada!'\n",[33,757,758,796,800,830],{"__ignoreMap":61},[65,759,760,762,765,767,770,772,775,778,780,783,785,788,790,793],{"class":67,"line":68},[65,761,232],{"class":103},[65,763,764],{"class":93}," greet",[65,766,96],{"class":71},[65,768,769],{"class":99},"greeting",[65,771,79],{"class":71},[65,773,774],{"class":99},"name",[65,776,777],{"class":71},") { ",[65,779,217],{"class":103},[65,781,782],{"class":179}," `${",[65,784,769],{"class":71},[65,786,787],{"class":179},"}, ${",[65,789,774],{"class":71},[65,791,792],{"class":179},"}!`",[65,794,795],{"class":71}," }\n",[65,797,798],{"class":67,"line":123},[65,799,281],{"emptyLinePlaceholder":280},[65,801,802,804,807,809,812,815,817,820,822,825,827],{"class":67,"line":168},[65,803,287],{"class":103},[65,805,806],{"class":75}," sayHello",[65,808,293],{"class":103},[65,810,811],{"class":71}," greet.",[65,813,814],{"class":93},"bind",[65,816,96],{"class":71},[65,818,819],{"class":75},"null",[65,821,79],{"class":71},[65,823,824],{"class":179},"'Hello'",[65,826,334],{"class":71},[65,828,829],{"class":119},"\u002F\u002F fix the greeting\n",[65,831,832,835,837,840,842],{"class":67,"line":277},[65,833,834],{"class":93},"sayHello",[65,836,96],{"class":71},[65,838,839],{"class":179},"'Ada'",[65,841,334],{"class":71},[65,843,844],{"class":119},"\u002F\u002F 'Hello, Ada!'\n",[15,846,847,848,851],{},"You can also write a generic ",[33,849,850],{},"partial"," HOF that captures leading arguments and forwards the\nrest — useful for adapting general functions to specific call sites.",[10,853,855],{"id":854},"memoization","Memoization",[15,857,858,860],{},[19,859,855],{}," is a HOF that wraps a function to cache its results by arguments, so repeated\ncalls with the same input return instantly. Great for pure, expensive computations.",[56,862,864],{"className":58,"code":863,"language":60,"meta":61,"style":61},"function memoize(fn) {\n  const cache = new Map()\n  return function (...args) {\n    const key = JSON.stringify(args)\n    if (cache.has(key)) return cache.get(key)   \u002F\u002F cache hit\n    const result = fn.apply(this, args)\n    cache.set(key, result)\n    return result\n  }\n}\n\nconst slowSquare = (n) => { \u002F* expensive *\u002F return n * n }\nconst fastSquare = memoize(slowSquare)\n",[33,865,866,879,898,914,935,963,985,996,1004,1009,1014,1019,1053],{"__ignoreMap":61},[65,867,868,870,873,875,877],{"class":67,"line":68},[65,869,232],{"class":103},[65,871,872],{"class":93}," memoize",[65,874,96],{"class":71},[65,876,425],{"class":99},[65,878,243],{"class":71},[65,880,881,884,887,889,892,895],{"class":67,"line":123},[65,882,883],{"class":103},"  const",[65,885,886],{"class":75}," cache",[65,888,293],{"class":103},[65,890,891],{"class":103}," new",[65,893,894],{"class":93}," Map",[65,896,897],{"class":71},"()\n",[65,899,900,902,905,907,909,912],{"class":67,"line":168},[65,901,248],{"class":103},[65,903,904],{"class":103}," function",[65,906,251],{"class":71},[65,908,392],{"class":103},[65,910,911],{"class":99},"args",[65,913,243],{"class":71},[65,915,916,919,922,924,927,929,932],{"class":67,"line":277},[65,917,918],{"class":103},"    const",[65,920,921],{"class":75}," key",[65,923,293],{"class":103},[65,925,926],{"class":75}," JSON",[65,928,43],{"class":71},[65,930,931],{"class":93},"stringify",[65,933,934],{"class":71},"(args)\n",[65,936,937,940,943,946,949,951,954,957,960],{"class":67,"line":284},[65,938,939],{"class":103},"    if",[65,941,942],{"class":71}," (cache.",[65,944,945],{"class":93},"has",[65,947,948],{"class":71},"(key)) ",[65,950,217],{"class":103},[65,952,953],{"class":71}," cache.",[65,955,956],{"class":93},"get",[65,958,959],{"class":71},"(key)   ",[65,961,962],{"class":119},"\u002F\u002F cache hit\n",[65,964,965,967,970,972,975,978,980,982],{"class":67,"line":305},[65,966,918],{"class":103},[65,968,969],{"class":75}," result",[65,971,293],{"class":103},[65,973,974],{"class":71}," fn.",[65,976,977],{"class":93},"apply",[65,979,96],{"class":71},[65,981,195],{"class":75},[65,983,984],{"class":71},", args)\n",[65,986,987,990,993],{"class":67,"line":323},[65,988,989],{"class":71},"    cache.",[65,991,992],{"class":93},"set",[65,994,995],{"class":71},"(key, result)\n",[65,997,998,1001],{"class":67,"line":340},[65,999,1000],{"class":103},"    return",[65,1002,1003],{"class":71}," result\n",[65,1005,1006],{"class":67,"line":572},[65,1007,1008],{"class":71},"  }\n",[65,1010,1012],{"class":67,"line":1011},10,[65,1013,274],{"class":71},[65,1015,1017],{"class":67,"line":1016},11,[65,1018,281],{"emptyLinePlaceholder":280},[65,1020,1022,1024,1027,1029,1031,1033,1035,1037,1040,1043,1046,1048,1050],{"class":67,"line":1021},12,[65,1023,287],{"class":103},[65,1025,1026],{"class":93}," slowSquare",[65,1028,293],{"class":103},[65,1030,251],{"class":71},[65,1032,100],{"class":99},[65,1034,256],{"class":71},[65,1036,259],{"class":103},[65,1038,1039],{"class":71}," { ",[65,1041,1042],{"class":119},"\u002F* expensive *\u002F",[65,1044,1045],{"class":103}," return",[65,1047,107],{"class":71},[65,1049,110],{"class":103},[65,1051,1052],{"class":71}," n }\n",[65,1054,1056,1058,1061,1063,1065],{"class":67,"line":1055},13,[65,1057,287],{"class":103},[65,1059,1060],{"class":75}," fastSquare",[65,1062,293],{"class":103},[65,1064,872],{"class":93},[65,1066,1067],{"class":71},"(slowSquare)\n",[15,1069,1070,1071,1074,1075,1078],{},"The ",[33,1072,1073],{},"cache"," lives in the returned closure, persisting across calls. Memoization only works for\n",[19,1076,1077],{},"pure"," functions (same input -> same output) and trades memory for speed — be mindful of\nunbounded cache growth.",[10,1080,1082],{"id":1081},"debounce-and-throttle","Debounce and throttle",[15,1084,1085,1086,1089,1090,1093],{},"Two HOFs critical for performance with frequent events (scroll, resize, input): ",[19,1087,1088],{},"debounce","\ndelays a function until activity stops, and ",[19,1091,1092],{},"throttle"," caps how often it can run. Both\nreturn a wrapped function that manages timers in a closure.",[56,1095,1097],{"className":58,"code":1096,"language":60,"meta":61,"style":61},"function debounce(fn, delay) {\n  let timer\n  return function (...args) {\n    clearTimeout(timer)\n    timer = setTimeout(() => fn.apply(this, args), delay)   \u002F\u002F reset on each call\n  }\n}\n\nconst onSearch = debounce(query => fetchResults(query), 300)\n",[33,1098,1099,1117,1125,1139,1147,1177,1181,1185,1189],{"__ignoreMap":61},[65,1100,1101,1103,1106,1108,1110,1112,1115],{"class":67,"line":68},[65,1102,232],{"class":103},[65,1104,1105],{"class":93}," debounce",[65,1107,96],{"class":71},[65,1109,425],{"class":99},[65,1111,79],{"class":71},[65,1113,1114],{"class":99},"delay",[65,1116,243],{"class":71},[65,1118,1119,1122],{"class":67,"line":123},[65,1120,1121],{"class":103},"  let",[65,1123,1124],{"class":71}," timer\n",[65,1126,1127,1129,1131,1133,1135,1137],{"class":67,"line":168},[65,1128,248],{"class":103},[65,1130,904],{"class":103},[65,1132,251],{"class":71},[65,1134,392],{"class":103},[65,1136,911],{"class":99},[65,1138,243],{"class":71},[65,1140,1141,1144],{"class":67,"line":277},[65,1142,1143],{"class":93},"    clearTimeout",[65,1145,1146],{"class":71},"(timer)\n",[65,1148,1149,1152,1155,1158,1161,1163,1165,1167,1169,1171,1174],{"class":67,"line":284},[65,1150,1151],{"class":71},"    timer ",[65,1153,1154],{"class":103},"=",[65,1156,1157],{"class":93}," setTimeout",[65,1159,1160],{"class":71},"(() ",[65,1162,259],{"class":103},[65,1164,974],{"class":71},[65,1166,977],{"class":93},[65,1168,96],{"class":71},[65,1170,195],{"class":75},[65,1172,1173],{"class":71},", args), delay)   ",[65,1175,1176],{"class":119},"\u002F\u002F reset on each call\n",[65,1178,1179],{"class":67,"line":305},[65,1180,1008],{"class":71},[65,1182,1183],{"class":67,"line":323},[65,1184,274],{"class":71},[65,1186,1187],{"class":67,"line":340},[65,1188,281],{"emptyLinePlaceholder":280},[65,1190,1191,1193,1196,1198,1200,1202,1205,1207,1210,1213,1216],{"class":67,"line":572},[65,1192,287],{"class":103},[65,1194,1195],{"class":75}," onSearch",[65,1197,293],{"class":103},[65,1199,1105],{"class":93},[65,1201,96],{"class":71},[65,1203,1204],{"class":99},"query",[65,1206,104],{"class":103},[65,1208,1209],{"class":93}," fetchResults",[65,1211,1212],{"class":71},"(query), ",[65,1214,1215],{"class":75},"300",[65,1217,302],{"class":71},[15,1219,1220],{},"Debounce is ideal for search-as-you-type (wait until the user pauses); throttle suits\nscroll\u002Fresize handlers (run at most every N ms). Both prevent expensive work from firing on\nevery single event.",[10,1222,1224],{"id":1223},"once-run-at-most-one-time","once: run at most one time",[15,1226,1227],{},"A small but illustrative HOF wraps a function so it runs only the first time, caching its\nresult thereafter — handy for one-time initialization.",[56,1229,1231],{"className":58,"code":1230,"language":60,"meta":61,"style":61},"function once(fn) {\n  let called = false, result\n  return function (...args) {\n    if (!called) { called = true; result = fn.apply(this, args) }\n    return result   \u002F\u002F subsequent calls return the cached result\n  }\n}\n",[33,1232,1233,1246,1261,1275,1308,1318,1322],{"__ignoreMap":61},[65,1234,1235,1237,1240,1242,1244],{"class":67,"line":68},[65,1236,232],{"class":103},[65,1238,1239],{"class":93}," once",[65,1241,96],{"class":71},[65,1243,425],{"class":99},[65,1245,243],{"class":71},[65,1247,1248,1250,1253,1255,1258],{"class":67,"line":123},[65,1249,1121],{"class":103},[65,1251,1252],{"class":71}," called ",[65,1254,1154],{"class":103},[65,1256,1257],{"class":75}," false",[65,1259,1260],{"class":71},", result\n",[65,1262,1263,1265,1267,1269,1271,1273],{"class":67,"line":168},[65,1264,248],{"class":103},[65,1266,904],{"class":103},[65,1268,251],{"class":71},[65,1270,392],{"class":103},[65,1272,911],{"class":99},[65,1274,243],{"class":71},[65,1276,1277,1279,1281,1284,1287,1289,1292,1295,1297,1299,1301,1303,1305],{"class":67,"line":277},[65,1278,939],{"class":103},[65,1280,251],{"class":71},[65,1282,1283],{"class":103},"!",[65,1285,1286],{"class":71},"called) { called ",[65,1288,1154],{"class":103},[65,1290,1291],{"class":75}," true",[65,1293,1294],{"class":71},"; result ",[65,1296,1154],{"class":103},[65,1298,974],{"class":71},[65,1300,977],{"class":93},[65,1302,96],{"class":71},[65,1304,195],{"class":75},[65,1306,1307],{"class":71},", args) }\n",[65,1309,1310,1312,1315],{"class":67,"line":284},[65,1311,1000],{"class":103},[65,1313,1314],{"class":71}," result   ",[65,1316,1317],{"class":119},"\u002F\u002F subsequent calls return the cached result\n",[65,1319,1320],{"class":67,"line":305},[65,1321,1008],{"class":71},[65,1323,1324],{"class":67,"line":323},[65,1325,274],{"class":71},[15,1327,1328,1329,43],{},"This pattern uses the same closure-over-state technique as memoize and debounce — a recurring\ntheme: ",[19,1330,1331],{},"HOFs that return stateful wrappers",[10,1333,1335],{"id":1334},"why-hofs-matter","Why HOFs matter",[15,1337,1338,1339,79,1341,1343,1344,1346],{},"Higher-order functions let you treat behavior as data, eliminating duplication and enabling\ndeclarative code. Instead of copy-pasting loops with slightly different bodies, you write the\nloop once (",[33,1340,35],{},[33,1342,140],{},") and vary the function. Instead of repeating timing logic, you\nwrite ",[33,1345,1088],{}," once. This is the essence of abstraction in functional JavaScript — and why\nthe technique appears everywhere from React hooks to middleware to Array methods.",[10,1348,1350],{"id":1349},"key-takeaways","Key takeaways",[1352,1353,1354,1358,1368,1371,1380,1387],"ul",{},[1355,1356,1357],"li",{},"A higher-order function takes a function as an argument, returns one, or both — enabled by\nfirst-class functions.",[1355,1359,1360,1361,1364,1365,1367],{},"Callbacks (passing functions in) power array methods and event APIs; watch the\n",[33,1362,1363],{},"map(parseInt)"," and lost-",[33,1366,195],{}," traps.",[1355,1369,1370],{},"Returning functions creates factories, currying, and partial application for reusable,\nspecialized functions.",[1355,1372,1373,547,1375,1377,1378,43],{},[33,1374,594],{},[33,1376,590],{}," build pipelines from small functions using ",[33,1379,468],{},[1355,1381,1382,1383,1386],{},"Memoize, debounce, throttle, and once are HOFs that return ",[19,1384,1385],{},"stateful wrappers"," using\nclosures.",[1355,1388,1389],{},"HOFs let you treat behavior as data — the foundation of declarative, DRY JavaScript.",[15,1391,1392],{},"Once you see functions as values you can pass and return, a whole expressive, reusable style of\nprogramming opens up — and you understand the machinery behind the tools you use every day.",[1394,1395,1396],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":61,"searchDepth":123,"depth":123,"links":1398},[1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409],{"id":12,"depth":123,"text":13},{"id":46,"depth":123,"text":47},{"id":210,"depth":123,"text":211},{"id":366,"depth":123,"text":367},{"id":600,"depth":123,"text":601},{"id":738,"depth":123,"text":739},{"id":854,"depth":123,"text":855},{"id":1081,"depth":123,"text":1082},{"id":1223,"depth":123,"text":1224},{"id":1334,"depth":123,"text":1335},{"id":1349,"depth":123,"text":1350},"Master higher-order functions in JavaScript — functions that take or return functions. Learn callbacks, composition, currying, partial application, memoization, debounce and throttle.","medium","md","JavaScript","javascript",{},"\u002Fblog\u002Fjavascript-higher-order-functions","\u002Fjavascript\u002Ffunctions\u002Fhigher-order-functions",{"title":5,"description":1410},"blog\u002Fjavascript-higher-order-functions","Higher-Order Functions","Functions","functions","2026-06-18","kIdnc0QVPBmMPP7G0eFXwBuLjDar3e_6umnr0l7dgrc",1781808673080]