[{"data":1,"prerenderedAt":3762},["ShallowReactive",2],{"\u002Fblog\u002Fclosures-a-fondo-en-javascript":3,"\u002Fblog\u002Fclosures-a-fondo-en-javascript-surround":3755},{"id":4,"title":5,"body":6,"categories":3743,"description":3745,"extension":3746,"image":3747,"meta":3748,"minRead":1375,"navigation":87,"path":3749,"pubDate":3750,"rawbody":3751,"seo":3752,"stem":3753,"__hash__":3754},"blog\u002Fblog\u002Fclosures-a-fondo-en-javascript.md","Closures a fondo en JavaScript",{"type":7,"value":8,"toc":3726},"minimark",[9,18,21,26,29,177,211,223,240,399,419,434,475,493,548,583,707,739,769,773,798,819,845,851,857,861,864,956,978,981,1105,1111,1120,1126,1226,1232,1396,1400,1403,1407,1410,1477,1494,1829,1845,1877,1881,1884,1982,1985,2126,2167,2178,2273,2276,2280,2283,2294,2588,2623,2627,2630,2701,2725,2810,2821,2876,2929,3025,3059,3063,3072,3151,3154,3272,3283,3286,3424,3430,3433,3449,3452,3632,3661,3674,3678,3681,3713,3717,3720,3723],[10,11,12,13,17],"p",{},"Cuando comencé a aprender sobre las closures, escuché y leí muchas veces explicaciones como esta: ",[14,15,16],"em",{},"\"Una closure es una función\nque retorna otra función, y la función que se retorna usa variables que se definieron en el cuerpo de la función padre\"",", o\nvarias explicaciones que prácticamente se referían a algo similar a esta definición, y aunque en el escenario que se expone en\nesta definición se forma una closure, la definición como tal no es 100% correcta y hay muchas otras cosas que podemos aprender\npara profundizar en el uso y comportamiento de las closures.",[10,19,20],{},"En este artículo exploramos a fondo qué son las closures, así como otros conceptos del lenguaje JavaScript, como el entorno léxico,\nque nos ayudarán a comprender el funcionamiento interno de las mismas. Aprenderemos cómo es que estos conceptos se relacionan\ndirectamente con los alcances de bloque(scopes) introducidos en la especificación ECMAScript 6, así como la relación que tienen\ncon las closures, y cómo el entender estos mecanismos nos ayudarán a comprender cómo es que al usar closures se pueden mantener\n\"vivas\" variables, constantes, parámetros y demás dentro de su alcance, incluso cuando la función donde fueron creadas hayan\nterminado su ejecución. Si te interesa conocer todo esto te invito a leer hasta al final porque hay mucha información interesante y\nseguro que algo nuevo aprendes hoy.",[22,23,25],"h2",{"id":24},"qué-son-las-closures","¿Qué son las closures?",[10,27,28],{},"Un closure es la combinación de una función agrupada dentro de otra con referencias a su estado adyacente. Veamos el siguiente\nejemplo para entenderlo un poco mejor:",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","function padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n      \u002F\u002F hijo es la función interna que forma el closure\n    console.log(nombre) \u002F\u002F Podemos acceder a la variable nombre\n  }\n\n  hijo()\n}\n\npadre() \u002F\u002F Se muestra en la consola 'pemid'\n","js","",[37,38,39,59,82,89,102,109,134,140,145,154,160,165],"code",{"__ignoreMap":35},[40,41,44,48,52,56],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"spNyl","function",[40,49,51],{"class":50},"s2Zo4"," padre",[40,53,55],{"class":54},"sMK4o","()",[40,57,58],{"class":54}," {\n",[40,60,62,65,69,72,75,79],{"class":42,"line":61},2,[40,63,64],{"class":46},"  let",[40,66,68],{"class":67},"sTEyZ"," nombre",[40,70,71],{"class":54}," =",[40,73,74],{"class":54}," '",[40,76,78],{"class":77},"sfazB","pemid",[40,80,81],{"class":54},"'\n",[40,83,85],{"class":42,"line":84},3,[40,86,88],{"emptyLinePlaceholder":87},true,"\n",[40,90,92,95,98,100],{"class":42,"line":91},4,[40,93,94],{"class":46},"  function",[40,96,97],{"class":50}," hijo",[40,99,55],{"class":54},[40,101,58],{"class":54},[40,103,105],{"class":42,"line":104},5,[40,106,108],{"class":107},"sHwdD","      \u002F\u002F hijo es la función interna que forma el closure\n",[40,110,112,115,118,121,125,128,131],{"class":42,"line":111},6,[40,113,114],{"class":67},"    console",[40,116,117],{"class":54},".",[40,119,120],{"class":50},"log",[40,122,124],{"class":123},"swJcz","(",[40,126,127],{"class":67},"nombre",[40,129,130],{"class":123},") ",[40,132,133],{"class":107},"\u002F\u002F Podemos acceder a la variable nombre\n",[40,135,137],{"class":42,"line":136},7,[40,138,139],{"class":54},"  }\n",[40,141,143],{"class":42,"line":142},8,[40,144,88],{"emptyLinePlaceholder":87},[40,146,148,151],{"class":42,"line":147},9,[40,149,150],{"class":50},"  hijo",[40,152,153],{"class":123},"()\n",[40,155,157],{"class":42,"line":156},10,[40,158,159],{"class":54},"}\n",[40,161,163],{"class":42,"line":162},11,[40,164,88],{"emptyLinePlaceholder":87},[40,166,168,171,174],{"class":42,"line":167},12,[40,169,170],{"class":50},"padre",[40,172,173],{"class":67},"() ",[40,175,176],{"class":107},"\u002F\u002F Se muestra en la consola 'pemid'\n",[10,178,179,180,183,184,186,187,189,190,192,193,199,200,205,206,117],{},"En este ejemplo podemos ver que en la función ",[37,181,182],{},"hijo"," se lee la variable declarada en la función ",[37,185,170],{},", prácticamente, en este\nejemplo la closure se crea entre al función ",[37,188,182],{}," y la variable declarada en la función ",[37,191,170],{},". Si has programado con JavaScript\no TypeScript durante un tiempo te habrás percatado de que realmente esto se relaciona directamente con otro concepto que también\nes muy importante desde inicio que es el ",[14,194,195],{},[196,197,198],"strong",{},"scope"," o alcance, y esto mismo se relaciona con los conceptos de ",[14,201,202],{},[196,203,204],{},"Ámbito Léxico","\ny ",[14,207,208],{},[196,209,210],{},"Entorno Léxico",[212,213,215,216,219,220],"h3",{"id":214},"alcance-con-let-y-const","Alcance con ",[37,217,218],{},"let"," y ",[37,221,222],{},"const",[10,224,225,226,229,230,235,236,239],{},"Antes de conocer lo que son el Ámbito Léxico y el Entorno Léxico, conozcamos el contexto en que estos conceptos fueron concebidos\nen JavaScript. En JavaScript tradicional, antes de la llegada de la especificación ECMAScript 6(ES6), las variables eran declaradas\ncon la palabra reservada ",[37,227,228],{},"var",", con estas variables, JavaScript hacia un proceso de ",[14,231,232],{},[196,233,234],{},"hoisting",", el cual ",[14,237,238],{},"\"elevaba\""," la\ndeclaración de las variables al inicio de la ejecución del archivo o módulo, lo cual hacía que pudieras usarlas incluso antes de su\ndeclaración o inicialización explícita, tal y como se muestra en el siguiente ejemplo:",[30,241,243],{"className":32,"code":242,"language":34,"meta":35,"style":35},"var x \u002F\u002F declarada, inicializada con undefined\n\nconsole.log(x) \u002F\u002F undefined\nconsole.log(y) \u002F\u002F undefined\n\u002F\u002F la variable \"y\" se puede usar antes de su declaración debido al proceso de hoisting \n\nx = 5\n\nif (true) {\n  var y \u002F\u002F Declarada, \"hoisteada\" e inicializada en undefined\n  console.log(x) \u002F\u002F 5\n}\n\ny = 10\n\nconsole.log(y) \u002F\u002F 10\n",[37,244,245,255,259,274,287,292,296,308,312,330,341,360,364,369,380,385],{"__ignoreMap":35},[40,246,247,249,252],{"class":42,"line":43},[40,248,228],{"class":46},[40,250,251],{"class":67}," x ",[40,253,254],{"class":107},"\u002F\u002F declarada, inicializada con undefined\n",[40,256,257],{"class":42,"line":61},[40,258,88],{"emptyLinePlaceholder":87},[40,260,261,264,266,268,271],{"class":42,"line":84},[40,262,263],{"class":67},"console",[40,265,117],{"class":54},[40,267,120],{"class":50},[40,269,270],{"class":67},"(x) ",[40,272,273],{"class":107},"\u002F\u002F undefined\n",[40,275,276,278,280,282,285],{"class":42,"line":91},[40,277,263],{"class":67},[40,279,117],{"class":54},[40,281,120],{"class":50},[40,283,284],{"class":67},"(y) ",[40,286,273],{"class":107},[40,288,289],{"class":42,"line":104},[40,290,291],{"class":107},"\u002F\u002F la variable \"y\" se puede usar antes de su declaración debido al proceso de hoisting \n",[40,293,294],{"class":42,"line":111},[40,295,88],{"emptyLinePlaceholder":87},[40,297,298,301,304],{"class":42,"line":136},[40,299,300],{"class":67},"x ",[40,302,303],{"class":54},"=",[40,305,307],{"class":306},"sbssI"," 5\n",[40,309,310],{"class":42,"line":142},[40,311,88],{"emptyLinePlaceholder":87},[40,313,314,318,321,325,327],{"class":42,"line":147},[40,315,317],{"class":316},"s7zQu","if",[40,319,320],{"class":67}," (",[40,322,324],{"class":323},"sfNiH","true",[40,326,130],{"class":67},[40,328,329],{"class":54},"{\n",[40,331,332,335,338],{"class":42,"line":156},[40,333,334],{"class":46},"  var",[40,336,337],{"class":67}," y",[40,339,340],{"class":107}," \u002F\u002F Declarada, \"hoisteada\" e inicializada en undefined\n",[40,342,343,346,348,350,352,355,357],{"class":42,"line":162},[40,344,345],{"class":67},"  console",[40,347,117],{"class":54},[40,349,120],{"class":50},[40,351,124],{"class":123},[40,353,354],{"class":67},"x",[40,356,130],{"class":123},[40,358,359],{"class":107},"\u002F\u002F 5\n",[40,361,362],{"class":42,"line":167},[40,363,159],{"class":54},[40,365,367],{"class":42,"line":366},13,[40,368,88],{"emptyLinePlaceholder":87},[40,370,372,375,377],{"class":42,"line":371},14,[40,373,374],{"class":67},"y ",[40,376,303],{"class":54},[40,378,379],{"class":306}," 10\n",[40,381,383],{"class":42,"line":382},15,[40,384,88],{"emptyLinePlaceholder":87},[40,386,388,390,392,394,396],{"class":42,"line":387},16,[40,389,263],{"class":67},[40,391,117],{"class":54},[40,393,120],{"class":50},[40,395,284],{"class":67},[40,397,398],{"class":107},"\u002F\u002F 10\n",[10,400,401,402,219,404,406,407,412,413,418],{},"Esto como te puedes imaginar, podía causar bugs muy complicados de encontrar. Con la llegada de ES6, JavaScript introdujo nuevas\nformas de declarar variables y constantes, esto como sabemos es con las palabras reservadas ",[37,403,218],{},[37,405,222],{},", con esto llegaron\nnuevos conceptos, entre los cuales están las ",[14,408,409],{},[196,410,411],{},"Temporal Dead Zones(TDZ)"," o zonas muertas temporales, y los ",[14,414,415],{},[196,416,417],{},"scopes"," o\nalcances de bloque.",[10,420,421,422,424,425,427,428,430,431,433],{},"La TDZ es la zona entre el inicio del bloque y la declaración de una variable, la cual prácticamente solo la vemos cuando declaramos\nuna variable con ",[37,423,218],{},", ya que al momento de declarar una constante con ",[37,426,222],{}," debemos obligatoriamente inicializarlas con un\nvalor. Gracias a esto, si intentamos hacer algo parecido a nuestro ejemplo anterior, pero ahora declarando la variable con ",[37,429,218],{}," en\nlugar de ",[37,432,228],{},", tendremos el siguiente error:",[30,435,437],{"className":32,"code":436,"language":34,"meta":35,"style":35},"console.log(x) \u002F\u002F ReferenceError: Cannot access 'x' before initialization\n\nlet x\n\nx = 5\n",[37,438,439,452,456,463,467],{"__ignoreMap":35},[40,440,441,443,445,447,449],{"class":42,"line":43},[40,442,263],{"class":67},[40,444,117],{"class":54},[40,446,120],{"class":50},[40,448,270],{"class":67},[40,450,451],{"class":107},"\u002F\u002F ReferenceError: Cannot access 'x' before initialization\n",[40,453,454],{"class":42,"line":61},[40,455,88],{"emptyLinePlaceholder":87},[40,457,458,460],{"class":42,"line":84},[40,459,218],{"class":46},[40,461,462],{"class":67}," x\n",[40,464,465],{"class":42,"line":91},[40,466,88],{"emptyLinePlaceholder":87},[40,468,469,471,473],{"class":42,"line":104},[40,470,300],{"class":67},[40,472,303],{"class":54},[40,474,307],{"class":306},[10,476,477,478,485,486,488,489,492],{},"Gracias a la TDZ, ahora si intentamos usar una variable antes de su declaración tendremos este error de\n",[14,479,480],{},[196,481,482],{},[37,483,484],{},"Reference Error: cannot access 'x' before initialization",". Es importante que sepamos que la TDZ solo es un mecanismo que\nhace que no se pueda acceder a una variable antes de su declaración, mas no de su inicialización, puesto que como ocurre con las\nvariables declaradas con ",[37,487,228],{},", si podemos acceder a ellas incluso antes de su inicialización ya que también JavaScript las\ninicializa en ",[37,490,491],{},"undefined"," como se muestra a continuación:",[30,494,496],{"className":32,"code":495,"language":34,"meta":35,"style":35},"let x\n\nconsole.log(x) \u002F\u002F undefined\n\nx = 5\n\nconsole.log(x) \u002F\u002F 5\n",[37,497,498,504,508,520,524,532,536],{"__ignoreMap":35},[40,499,500,502],{"class":42,"line":43},[40,501,218],{"class":46},[40,503,462],{"class":67},[40,505,506],{"class":42,"line":61},[40,507,88],{"emptyLinePlaceholder":87},[40,509,510,512,514,516,518],{"class":42,"line":84},[40,511,263],{"class":67},[40,513,117],{"class":54},[40,515,120],{"class":50},[40,517,270],{"class":67},[40,519,273],{"class":107},[40,521,522],{"class":42,"line":91},[40,523,88],{"emptyLinePlaceholder":87},[40,525,526,528,530],{"class":42,"line":104},[40,527,300],{"class":67},[40,529,303],{"class":54},[40,531,307],{"class":306},[40,533,534],{"class":42,"line":111},[40,535,88],{"emptyLinePlaceholder":87},[40,537,538,540,542,544,546],{"class":42,"line":136},[40,539,263],{"class":67},[40,541,117],{"class":54},[40,543,120],{"class":50},[40,545,270],{"class":67},[40,547,359],{"class":107},[10,549,550,551,555,556,558,559,562,563,565,566,568,569,571,572,575,576,578,579,582],{},"Otro concepto importante que llegó junto con ES6 es el ",[14,552,553],{},[196,554,198],{}," o alcance por bloque. Como vimos en nuestro ejemplo usando ",[37,557,228],{},",\nla variable ",[37,560,561],{},"y",", declarada dentro de un bloque, podía ser accedida desde fuera de las llaves --las llaves delimitan el bloque(este\ncomportamiento sigue existiendo en JavaScript moderno, por eso ya no se recomienda declarar variables con ",[37,564,228],{},"). El alcance por\nbloque se refiere a que las variables o constantes declaradas con ",[37,567,218],{}," o ",[37,570,222],{},", solo pueden ser leídas en el mismo bloque o en\nbloques adyacentes ",[14,573,574],{},"\"hijos\"",", pero las variables declaradas en bloques ",[14,577,574],{}," no pueden ser leídas o accedidas desde bloques\n",[14,580,581],{},"\"padres\""," o superiores, veamos el siguiente ejemplo para enterderlo mejor:",[30,584,586],{"className":32,"code":585,"language":34,"meta":35,"style":35},"let var1 = 'outer'\n\nif (true) {\n  let var2 = 'inner'\n  console.log(var1) \u002F\u002F 'outer'\n  console.log(var2) \u002F\u002F 'inner'\n}\n\nconsole.log(var1) \u002F\u002F 'outer'\nconsole.log(var2) \u002F\u002F ReferenceError: var2 is not defined\n",[37,587,588,604,608,620,636,654,672,676,680,693],{"__ignoreMap":35},[40,589,590,592,595,597,599,602],{"class":42,"line":43},[40,591,218],{"class":46},[40,593,594],{"class":67}," var1 ",[40,596,303],{"class":54},[40,598,74],{"class":54},[40,600,601],{"class":77},"outer",[40,603,81],{"class":54},[40,605,606],{"class":42,"line":61},[40,607,88],{"emptyLinePlaceholder":87},[40,609,610,612,614,616,618],{"class":42,"line":84},[40,611,317],{"class":316},[40,613,320],{"class":67},[40,615,324],{"class":323},[40,617,130],{"class":67},[40,619,329],{"class":54},[40,621,622,624,627,629,631,634],{"class":42,"line":91},[40,623,64],{"class":46},[40,625,626],{"class":67}," var2",[40,628,71],{"class":54},[40,630,74],{"class":54},[40,632,633],{"class":77},"inner",[40,635,81],{"class":54},[40,637,638,640,642,644,646,649,651],{"class":42,"line":104},[40,639,345],{"class":67},[40,641,117],{"class":54},[40,643,120],{"class":50},[40,645,124],{"class":123},[40,647,648],{"class":67},"var1",[40,650,130],{"class":123},[40,652,653],{"class":107},"\u002F\u002F 'outer'\n",[40,655,656,658,660,662,664,667,669],{"class":42,"line":111},[40,657,345],{"class":67},[40,659,117],{"class":54},[40,661,120],{"class":50},[40,663,124],{"class":123},[40,665,666],{"class":67},"var2",[40,668,130],{"class":123},[40,670,671],{"class":107},"\u002F\u002F 'inner'\n",[40,673,674],{"class":42,"line":136},[40,675,159],{"class":54},[40,677,678],{"class":42,"line":142},[40,679,88],{"emptyLinePlaceholder":87},[40,681,682,684,686,688,691],{"class":42,"line":147},[40,683,263],{"class":67},[40,685,117],{"class":54},[40,687,120],{"class":50},[40,689,690],{"class":67},"(var1) ",[40,692,653],{"class":107},[40,694,695,697,699,701,704],{"class":42,"line":156},[40,696,263],{"class":67},[40,698,117],{"class":54},[40,700,120],{"class":50},[40,702,703],{"class":67},"(var2) ",[40,705,706],{"class":107},"\u002F\u002F ReferenceError: var2 is not defined\n",[10,708,709,710,712,713,715,716,719,720,722,723,726,727,729,730,733,734,736,737,117],{},"En este último ejemplo, la variable ",[37,711,648],{}," puede ser accedida desde el bloque del ",[37,714,317],{}," puesto que es una variable que se declaró\nen un bloque ",[14,717,718],{},"\"padre\"","(también se puede decir que se declaró en el ámbito externo), sin embargo como vemos al final, cuando\nintentamos acceder a ",[37,721,666],{},", que está declarada dentro del bloque ",[14,724,725],{},"\"hijo\"","(dentro de las llaves del ",[37,728,317],{},"), JavaScript nos arroja\nun ",[14,731,732],{},"ReferenceError",", pues como mencionamos antes, los bloques ",[14,735,718],{}," no pueden acceder a las variables declaradas en los bloques\n(o ámbitos) ",[14,738,725],{},[10,740,741,742,744,745,747,748,750,751,756,757,760,761,756,765,768],{},"Con esto, ahora los bloques en JavaScript crean ámbitos o ",[14,743,417],{},", como lo vimos en este último ejemplo, el alcance de la variable\n",[37,746,666],{},", sólo es dentro del bloque entre las llaves de la sentencia ",[37,749,317],{},", por este comportamiento llegaron otros conceptos nuevos que\ndebemos conocer para comprender a fondo las closures, los cuales son el ",[14,752,753],{},[196,754,755],{},"Ámbito\u002FAlcance Léxico","(o ",[14,758,759],{},"lexical scope",") y el\n",[14,762,763],{},[196,764,210],{},[14,766,767],{},"lexical environment",").",[212,770,772],{"id":771},"ámbito-léxico-y-entorno-léxico","Ámbito Léxico y Entorno Léxico",[10,774,775,776,219,778,780,781,783,784,788,789,792,793,797],{},"Con la llegada de ",[37,777,218],{},[37,779,222],{}," en ES6, como mencionamos, los bloques crean ",[14,782,417],{},", con esto, podemos definir el\n",[14,785,786],{},[196,787,204],{}," como un concepto o regla del lenguaje JavaScript que determina la visibilidad y accesibilidad de las variables\nsegún donde se escribieron ",[14,790,791],{},"\"físicamente\""," en el código; por otro lado, el ",[14,794,795],{},[196,796,210],{}," es la implementación física que usa\nel motor de JavaScript para almacenar esas variables y mantener la referencia al ámbito padre.",[10,799,800,801,805,806,808,809,813,814,818],{},"En otras palabras, el ",[14,802,803],{},[196,804,204],{}," son las reglas del estándar ECMAScript que determinan cuál es el alcance o ",[14,807,198],{}," de las\nvariables, mientras que el ",[14,810,811],{},[196,812,210],{}," es el lugar físico en memoria donde se almacena la estructura de datos de las\nvariables de una función, el ",[14,815,816],{},[196,817,210],{}," se compone de dos elementos:",[820,821,822,835],"ul",{},[823,824,825,826,756,831,834],"li",{},"El ",[14,827,828],{},[196,829,830],{},"Registro de Entorno",[14,832,833],{},"Environment Record","): Es donde se almacenan las variables, constantes, funciones y parámetros\nlocales o declarados directamente dentro del scope de la función",[823,836,837,838,841,842,768],{},"Una referencia externa: La referencia o enlace al ",[14,839,840],{},"entorno léxico"," adyacente superior (",[14,843,844],{},"Outer Lexical Environment",[10,846,847,848,850],{},"Prácticamente es el ",[14,849,840],{}," lo que permite que las closures puedan crearse y lo que explica cómo funciona a más bajo nivel\nel alcance de las variables y constantes.",[10,852,853,854,117],{},"Un dato interesante y curioso es que algunas fuentes en internet mencionan que el entorno léxico de una función es almacenado en una\nvariable oculta llamada ",[37,855,856],{},"[[Environment]]",[22,858,860],{"id":859},"funciones-que-retornan-funciones","Funciones que retornan funciones",[10,862,863],{},"Veamos de nuevo nuestro primer ejemplo:",[30,865,866],{"className":32,"code":33,"language":34,"meta":35,"style":35},[37,867,868,878,892,896,906,910,926,930,934,940,944,948],{"__ignoreMap":35},[40,869,870,872,874,876],{"class":42,"line":43},[40,871,47],{"class":46},[40,873,51],{"class":50},[40,875,55],{"class":54},[40,877,58],{"class":54},[40,879,880,882,884,886,888,890],{"class":42,"line":61},[40,881,64],{"class":46},[40,883,68],{"class":67},[40,885,71],{"class":54},[40,887,74],{"class":54},[40,889,78],{"class":77},[40,891,81],{"class":54},[40,893,894],{"class":42,"line":84},[40,895,88],{"emptyLinePlaceholder":87},[40,897,898,900,902,904],{"class":42,"line":91},[40,899,94],{"class":46},[40,901,97],{"class":50},[40,903,55],{"class":54},[40,905,58],{"class":54},[40,907,908],{"class":42,"line":104},[40,909,108],{"class":107},[40,911,912,914,916,918,920,922,924],{"class":42,"line":111},[40,913,114],{"class":67},[40,915,117],{"class":54},[40,917,120],{"class":50},[40,919,124],{"class":123},[40,921,127],{"class":67},[40,923,130],{"class":123},[40,925,133],{"class":107},[40,927,928],{"class":42,"line":136},[40,929,139],{"class":54},[40,931,932],{"class":42,"line":142},[40,933,88],{"emptyLinePlaceholder":87},[40,935,936,938],{"class":42,"line":147},[40,937,150],{"class":50},[40,939,153],{"class":123},[40,941,942],{"class":42,"line":156},[40,943,159],{"class":54},[40,945,946],{"class":42,"line":162},[40,947,88],{"emptyLinePlaceholder":87},[40,949,950,952,954],{"class":42,"line":167},[40,951,170],{"class":50},[40,953,173],{"class":67},[40,955,176],{"class":107},[10,957,958,959,961,962,964,965,967,968,970,971,974,975,977],{},"En este ejemplo, la variable ",[37,960,127],{}," solo es usada dentro de la función ",[37,963,182],{}," y solo se imprime en consola, una vez la función\n",[37,966,170],{}," termina de ejecutarse, la variable ",[37,969,127],{}," es marcada como lista para limpieza por el recolector de basura(",[14,972,973],{},"garbage collector",")\ny la liberación de su espacio en memoria, lo que hace que una vez terminada de ejecutarse ya no se pueda volver a acceder a la\nvariable ",[37,976,127],{}," de ninguna manera.",[10,979,980],{},"Ahora bien, llegamos a la parte que se suele enseñar comúnmente cuando se explican las closures en JavaScript, las funciones que\nretornan funciones que tienen una referencia a una variable o constante declarada en la función padre, veamos este ejemplo:",[30,982,984],{"className":32,"code":983,"language":34,"meta":35,"style":35},"function padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n    console.log(nombre)\n  }\n\n  return hijo\n}\n\nconst funcionHijo = padre() \u002F\u002F guardamos la referencia a la función hijo\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\n",[37,985,986,996,1010,1014,1024,1039,1043,1047,1055,1059,1063,1079,1089,1097],{"__ignoreMap":35},[40,987,988,990,992,994],{"class":42,"line":43},[40,989,47],{"class":46},[40,991,51],{"class":50},[40,993,55],{"class":54},[40,995,58],{"class":54},[40,997,998,1000,1002,1004,1006,1008],{"class":42,"line":61},[40,999,64],{"class":46},[40,1001,68],{"class":67},[40,1003,71],{"class":54},[40,1005,74],{"class":54},[40,1007,78],{"class":77},[40,1009,81],{"class":54},[40,1011,1012],{"class":42,"line":84},[40,1013,88],{"emptyLinePlaceholder":87},[40,1015,1016,1018,1020,1022],{"class":42,"line":91},[40,1017,94],{"class":46},[40,1019,97],{"class":50},[40,1021,55],{"class":54},[40,1023,58],{"class":54},[40,1025,1026,1028,1030,1032,1034,1036],{"class":42,"line":104},[40,1027,114],{"class":67},[40,1029,117],{"class":54},[40,1031,120],{"class":50},[40,1033,124],{"class":123},[40,1035,127],{"class":67},[40,1037,1038],{"class":123},")\n",[40,1040,1041],{"class":42,"line":111},[40,1042,139],{"class":54},[40,1044,1045],{"class":42,"line":136},[40,1046,88],{"emptyLinePlaceholder":87},[40,1048,1049,1052],{"class":42,"line":142},[40,1050,1051],{"class":316},"  return",[40,1053,1054],{"class":67}," hijo\n",[40,1056,1057],{"class":42,"line":147},[40,1058,159],{"class":54},[40,1060,1061],{"class":42,"line":156},[40,1062,88],{"emptyLinePlaceholder":87},[40,1064,1065,1067,1070,1072,1074,1076],{"class":42,"line":162},[40,1066,222],{"class":46},[40,1068,1069],{"class":67}," funcionHijo ",[40,1071,303],{"class":54},[40,1073,51],{"class":50},[40,1075,173],{"class":67},[40,1077,1078],{"class":107},"\u002F\u002F guardamos la referencia a la función hijo\n",[40,1080,1081,1084,1086],{"class":42,"line":167},[40,1082,1083],{"class":50},"funcionHijo",[40,1085,173],{"class":67},[40,1087,1088],{"class":107},"\u002F\u002F 'pemid'\n",[40,1090,1091,1093,1095],{"class":42,"line":366},[40,1092,1083],{"class":50},[40,1094,173],{"class":67},[40,1096,1088],{"class":107},[40,1098,1099,1101,1103],{"class":42,"line":371},[40,1100,1083],{"class":50},[40,1102,173],{"class":67},[40,1104,1088],{"class":107},[10,1106,1107,1108,1110],{},"Podemos acceder a la variable ",[37,1109,127],{}," incluso cuando la función donde fue declarada ya terminó su ejecución!!! 🤯",[10,1112,1113,1114,1116,1117,1119],{},"Puede que esto te sorprenda, o puede que no porque es algo que ya has visto muchas veces y sabes que es el comportamiento que tienen\nlas closures, pero, ¿sabes realmente por qué podemos seguir accediendo a la variable ",[37,1115,127],{}," incluso después de que termina de\nejecutarse la función ",[37,1118,170],{},"?",[10,1121,1122,1123,1125],{},"Ahora que hemos aprendido lo que es el ",[14,1124,840],{},", no es tan complicado entender esto, prácticamente podemos resumir lo que\nestá pasando con lo siguiente:",[1127,1128,1129,1137,1163,1171,1188,1213],"ol",{},[823,1130,1131,1132,1134,1135,117],{},"Se declara la función ",[37,1133,170],{},", la cual en su cuerpo declara la variable ",[37,1136,127],{},[823,1138,1139,1140,1142,1143,1145,1146,1148,1149,1151,1152,1154,1155,1157,1158,1160,1161,117],{},"Dentro de la función ",[37,1141,170],{}," también se declara la función ",[37,1144,182],{},", como vimos antes, en la función ",[37,1147,182],{}," se crea un\n",[14,1150,840],{},", en el cual hay una referencia hacia el ",[14,1153,840],{}," superior(el de la función ",[37,1156,170],{},") y dentro de este\núltimo está la variable ",[37,1159,127],{}," que está siendo usada dentro de la función ",[37,1162,182],{},[823,1164,1165,1166,1168,1169,117],{},"La función ",[37,1167,182],{}," es retornada por la función ",[37,1170,170],{},[823,1172,1173,1174,124,1176,1179,1180,1182,1183,1185,1186,117],{},"Se declara la constante ",[37,1175,1083],{},[37,1177,1178],{},"const funcionHijo = padre()","), ahora en esta constante se guarda lo que retorna la función\n",[37,1181,170],{},", que es la referencia a la función ",[37,1184,182],{}," que fue declarada dentro de la función ",[37,1187,170],{},[823,1189,1190,1191,1193,1194,1196,1197,1199,1200,1202,1203,1205,1206,1209,1210,1212],{},"Se termina de ejecutar la función ",[37,1192,170],{},", JavaScript intente hacer la limpieza o recolección de las variables declaradas en la\nfunción ",[37,1195,170],{}," porque ya terminó su ejecución, sin embargo, al ver la variable ",[37,1198,127],{}," se da cuenta que esta sigue siendo\nreferenciada dentro del ",[14,1201,840],{}," de la función ",[37,1204,182],{},", la cual sigue teniendo una referencia ",[14,1207,1208],{},"\"viva\"",", la constante\n",[37,1211,1083],{},", por lo que al no poderla destruir, la pasa a la memoria heap, donde vivirá hasta que ya no sea utilizada ni\nreferenciada en ningún lugar.",[823,1214,1215,1216,1218,1219,1222,1223,117],{},"Gracias a que esta referencia ahora se queda ",[14,1217,1208],{},", al ejecutar ",[37,1220,1221],{},"funcionHijo()"," más adelante, podemos seguir viendo en la\nconsola ",[37,1224,1225],{},"'pemid'",[10,1227,1228,1229,1231],{},"Con esto ahora ya conoces más a fondo cómo es que funcionan las closures, ahora bien, solo para complementar esto, podríamos hacer\nuna limpieza manual de la referencia a la variable ",[37,1230,127],{}," de la siguiente manera:",[30,1233,1235],{"className":32,"code":1234,"language":34,"meta":35,"style":35},"function padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n    console.log(nombre)\n  }\n\n  return hijo\n}\n\n\u002F\u002F reemplazamos const por let para poder cambiar su valor más adelante\nlet funcionHijo = padre()\n\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\n\n\u002F\u002F Al cambiar ahora el valor guardado en la variable funcionHijo por undefined\n\u002F\u002F se pierde la referencia de la función hijo y su entorno léxico, por lo que\n\u002F\u002F ahora la variable nombre no se usa en ningún lugar por lo que puede ser\n\u002F\u002F destruida por el garbage collector\nfuncionHijo = undefined\n",[37,1236,1237,1247,1261,1265,1275,1289,1293,1297,1303,1307,1311,1316,1328,1332,1340,1348,1356,1361,1367,1373,1379,1385],{"__ignoreMap":35},[40,1238,1239,1241,1243,1245],{"class":42,"line":43},[40,1240,47],{"class":46},[40,1242,51],{"class":50},[40,1244,55],{"class":54},[40,1246,58],{"class":54},[40,1248,1249,1251,1253,1255,1257,1259],{"class":42,"line":61},[40,1250,64],{"class":46},[40,1252,68],{"class":67},[40,1254,71],{"class":54},[40,1256,74],{"class":54},[40,1258,78],{"class":77},[40,1260,81],{"class":54},[40,1262,1263],{"class":42,"line":84},[40,1264,88],{"emptyLinePlaceholder":87},[40,1266,1267,1269,1271,1273],{"class":42,"line":91},[40,1268,94],{"class":46},[40,1270,97],{"class":50},[40,1272,55],{"class":54},[40,1274,58],{"class":54},[40,1276,1277,1279,1281,1283,1285,1287],{"class":42,"line":104},[40,1278,114],{"class":67},[40,1280,117],{"class":54},[40,1282,120],{"class":50},[40,1284,124],{"class":123},[40,1286,127],{"class":67},[40,1288,1038],{"class":123},[40,1290,1291],{"class":42,"line":111},[40,1292,139],{"class":54},[40,1294,1295],{"class":42,"line":136},[40,1296,88],{"emptyLinePlaceholder":87},[40,1298,1299,1301],{"class":42,"line":142},[40,1300,1051],{"class":316},[40,1302,1054],{"class":67},[40,1304,1305],{"class":42,"line":147},[40,1306,159],{"class":54},[40,1308,1309],{"class":42,"line":156},[40,1310,88],{"emptyLinePlaceholder":87},[40,1312,1313],{"class":42,"line":162},[40,1314,1315],{"class":107},"\u002F\u002F reemplazamos const por let para poder cambiar su valor más adelante\n",[40,1317,1318,1320,1322,1324,1326],{"class":42,"line":167},[40,1319,218],{"class":46},[40,1321,1069],{"class":67},[40,1323,303],{"class":54},[40,1325,51],{"class":50},[40,1327,153],{"class":67},[40,1329,1330],{"class":42,"line":366},[40,1331,88],{"emptyLinePlaceholder":87},[40,1333,1334,1336,1338],{"class":42,"line":371},[40,1335,1083],{"class":50},[40,1337,173],{"class":67},[40,1339,1088],{"class":107},[40,1341,1342,1344,1346],{"class":42,"line":382},[40,1343,1083],{"class":50},[40,1345,173],{"class":67},[40,1347,1088],{"class":107},[40,1349,1350,1352,1354],{"class":42,"line":387},[40,1351,1083],{"class":50},[40,1353,173],{"class":67},[40,1355,1088],{"class":107},[40,1357,1359],{"class":42,"line":1358},17,[40,1360,88],{"emptyLinePlaceholder":87},[40,1362,1364],{"class":42,"line":1363},18,[40,1365,1366],{"class":107},"\u002F\u002F Al cambiar ahora el valor guardado en la variable funcionHijo por undefined\n",[40,1368,1370],{"class":42,"line":1369},19,[40,1371,1372],{"class":107},"\u002F\u002F se pierde la referencia de la función hijo y su entorno léxico, por lo que\n",[40,1374,1376],{"class":42,"line":1375},20,[40,1377,1378],{"class":107},"\u002F\u002F ahora la variable nombre no se usa en ningún lugar por lo que puede ser\n",[40,1380,1382],{"class":42,"line":1381},21,[40,1383,1384],{"class":107},"\u002F\u002F destruida por el garbage collector\n",[40,1386,1388,1391,1393],{"class":42,"line":1387},22,[40,1389,1390],{"class":67},"funcionHijo ",[40,1392,303],{"class":54},[40,1394,1395],{"class":54}," undefined\n",[22,1397,1399],{"id":1398},"usando-closures","Usando Closures",[10,1401,1402],{},"Hagamos algunos ejemplos de uso de closures para entender mejor algunas formas de usar closures.",[212,1404,1406],{"id":1405},"creando-fábricas-de-funciones","Creando fábricas de funciones",[10,1408,1409],{},"Veamos esta función:",[30,1411,1413],{"className":32,"code":1412,"language":34,"meta":35,"style":35},"function crearTablaDeMultiplicar(factor) {\n  return function (multiplier) {\n    console.log(factor * multiplier)\n  }\n}\n",[37,1414,1415,1433,1449,1469,1473],{"__ignoreMap":35},[40,1416,1417,1419,1422,1424,1428,1431],{"class":42,"line":43},[40,1418,47],{"class":46},[40,1420,1421],{"class":50}," crearTablaDeMultiplicar",[40,1423,124],{"class":54},[40,1425,1427],{"class":1426},"sHdIc","factor",[40,1429,1430],{"class":54},")",[40,1432,58],{"class":54},[40,1434,1435,1437,1440,1442,1445,1447],{"class":42,"line":61},[40,1436,1051],{"class":316},[40,1438,1439],{"class":46}," function",[40,1441,320],{"class":54},[40,1443,1444],{"class":1426},"multiplier",[40,1446,1430],{"class":54},[40,1448,58],{"class":54},[40,1450,1451,1453,1455,1457,1459,1461,1464,1467],{"class":42,"line":84},[40,1452,114],{"class":67},[40,1454,117],{"class":54},[40,1456,120],{"class":50},[40,1458,124],{"class":123},[40,1460,1427],{"class":67},[40,1462,1463],{"class":54}," *",[40,1465,1466],{"class":67}," multiplier",[40,1468,1038],{"class":123},[40,1470,1471],{"class":42,"line":91},[40,1472,139],{"class":54},[40,1474,1475],{"class":42,"line":104},[40,1476,159],{"class":54},[10,1478,1165,1479,1482,1483,1485,1486,1488,1489,219,1491,1493],{},[37,1480,1481],{},"crearTablaDeMultiplicar"," recibe el parámetro ",[37,1484,1427],{},", el cual se usa en la función anónima que retorno, esta función\nque retorna también recibe un parámetro ",[37,1487,1444],{},", como podemos ver en el código, se imprimirá en consola el producto resultante\nentre ",[37,1490,1427],{},[37,1492,1444],{},", lo cual podemos usar de la siguiente manera:",[30,1495,1497],{"className":32,"code":1496,"language":34,"meta":35,"style":35},"\u002F\u002F Tabla del 5\nconst _5x = crearTablaDeMultiplicar(5)\n\n_5x(1) \u002F\u002F 5\n_5x(2) \u002F\u002F 10\n_5x(3) \u002F\u002F 15\n_5x(4) \u002F\u002F 20\n_5x(5) \u002F\u002F 25\n_5x(6) \u002F\u002F 30\n_5x(7) \u002F\u002F 35\n_5x(8) \u002F\u002F 40\n_5x(9) \u002F\u002F 45\n_5x(10) \u002F\u002F 50\n\n\u002F\u002F Tabla del 7\nconst _7x = crearTablaDeMultiplicar(7)\n\n_7x(1) \u002F\u002F 7\n_7x(2) \u002F\u002F 14\n_7x(3) \u002F\u002F 21\n_7x(4) \u002F\u002F 28\n_7x(5) \u002F\u002F 35\n_7x(6) \u002F\u002F 42\n_7x(7) \u002F\u002F 49\n_7x(8) \u002F\u002F 56\n_7x(9) \u002F\u002F 63\n_7x(10) \u002F\u002F 70\n",[37,1498,1499,1504,1522,1526,1540,1553,1567,1581,1594,1608,1622,1636,1650,1664,1668,1673,1690,1694,1708,1721,1734,1747,1759,1773,1787,1801,1815],{"__ignoreMap":35},[40,1500,1501],{"class":42,"line":43},[40,1502,1503],{"class":107},"\u002F\u002F Tabla del 5\n",[40,1505,1506,1508,1511,1513,1515,1517,1520],{"class":42,"line":61},[40,1507,222],{"class":46},[40,1509,1510],{"class":67}," _5x ",[40,1512,303],{"class":54},[40,1514,1421],{"class":50},[40,1516,124],{"class":67},[40,1518,1519],{"class":306},"5",[40,1521,1038],{"class":67},[40,1523,1524],{"class":42,"line":84},[40,1525,88],{"emptyLinePlaceholder":87},[40,1527,1528,1531,1533,1536,1538],{"class":42,"line":91},[40,1529,1530],{"class":50},"_5x",[40,1532,124],{"class":67},[40,1534,1535],{"class":306},"1",[40,1537,130],{"class":67},[40,1539,359],{"class":107},[40,1541,1542,1544,1546,1549,1551],{"class":42,"line":104},[40,1543,1530],{"class":50},[40,1545,124],{"class":67},[40,1547,1548],{"class":306},"2",[40,1550,130],{"class":67},[40,1552,398],{"class":107},[40,1554,1555,1557,1559,1562,1564],{"class":42,"line":111},[40,1556,1530],{"class":50},[40,1558,124],{"class":67},[40,1560,1561],{"class":306},"3",[40,1563,130],{"class":67},[40,1565,1566],{"class":107},"\u002F\u002F 15\n",[40,1568,1569,1571,1573,1576,1578],{"class":42,"line":136},[40,1570,1530],{"class":50},[40,1572,124],{"class":67},[40,1574,1575],{"class":306},"4",[40,1577,130],{"class":67},[40,1579,1580],{"class":107},"\u002F\u002F 20\n",[40,1582,1583,1585,1587,1589,1591],{"class":42,"line":142},[40,1584,1530],{"class":50},[40,1586,124],{"class":67},[40,1588,1519],{"class":306},[40,1590,130],{"class":67},[40,1592,1593],{"class":107},"\u002F\u002F 25\n",[40,1595,1596,1598,1600,1603,1605],{"class":42,"line":147},[40,1597,1530],{"class":50},[40,1599,124],{"class":67},[40,1601,1602],{"class":306},"6",[40,1604,130],{"class":67},[40,1606,1607],{"class":107},"\u002F\u002F 30\n",[40,1609,1610,1612,1614,1617,1619],{"class":42,"line":156},[40,1611,1530],{"class":50},[40,1613,124],{"class":67},[40,1615,1616],{"class":306},"7",[40,1618,130],{"class":67},[40,1620,1621],{"class":107},"\u002F\u002F 35\n",[40,1623,1624,1626,1628,1631,1633],{"class":42,"line":162},[40,1625,1530],{"class":50},[40,1627,124],{"class":67},[40,1629,1630],{"class":306},"8",[40,1632,130],{"class":67},[40,1634,1635],{"class":107},"\u002F\u002F 40\n",[40,1637,1638,1640,1642,1645,1647],{"class":42,"line":167},[40,1639,1530],{"class":50},[40,1641,124],{"class":67},[40,1643,1644],{"class":306},"9",[40,1646,130],{"class":67},[40,1648,1649],{"class":107},"\u002F\u002F 45\n",[40,1651,1652,1654,1656,1659,1661],{"class":42,"line":366},[40,1653,1530],{"class":50},[40,1655,124],{"class":67},[40,1657,1658],{"class":306},"10",[40,1660,130],{"class":67},[40,1662,1663],{"class":107},"\u002F\u002F 50\n",[40,1665,1666],{"class":42,"line":371},[40,1667,88],{"emptyLinePlaceholder":87},[40,1669,1670],{"class":42,"line":382},[40,1671,1672],{"class":107},"\u002F\u002F Tabla del 7\n",[40,1674,1675,1677,1680,1682,1684,1686,1688],{"class":42,"line":387},[40,1676,222],{"class":46},[40,1678,1679],{"class":67}," _7x ",[40,1681,303],{"class":54},[40,1683,1421],{"class":50},[40,1685,124],{"class":67},[40,1687,1616],{"class":306},[40,1689,1038],{"class":67},[40,1691,1692],{"class":42,"line":1358},[40,1693,88],{"emptyLinePlaceholder":87},[40,1695,1696,1699,1701,1703,1705],{"class":42,"line":1363},[40,1697,1698],{"class":50},"_7x",[40,1700,124],{"class":67},[40,1702,1535],{"class":306},[40,1704,130],{"class":67},[40,1706,1707],{"class":107},"\u002F\u002F 7\n",[40,1709,1710,1712,1714,1716,1718],{"class":42,"line":1369},[40,1711,1698],{"class":50},[40,1713,124],{"class":67},[40,1715,1548],{"class":306},[40,1717,130],{"class":67},[40,1719,1720],{"class":107},"\u002F\u002F 14\n",[40,1722,1723,1725,1727,1729,1731],{"class":42,"line":1375},[40,1724,1698],{"class":50},[40,1726,124],{"class":67},[40,1728,1561],{"class":306},[40,1730,130],{"class":67},[40,1732,1733],{"class":107},"\u002F\u002F 21\n",[40,1735,1736,1738,1740,1742,1744],{"class":42,"line":1381},[40,1737,1698],{"class":50},[40,1739,124],{"class":67},[40,1741,1575],{"class":306},[40,1743,130],{"class":67},[40,1745,1746],{"class":107},"\u002F\u002F 28\n",[40,1748,1749,1751,1753,1755,1757],{"class":42,"line":1387},[40,1750,1698],{"class":50},[40,1752,124],{"class":67},[40,1754,1519],{"class":306},[40,1756,130],{"class":67},[40,1758,1621],{"class":107},[40,1760,1762,1764,1766,1768,1770],{"class":42,"line":1761},23,[40,1763,1698],{"class":50},[40,1765,124],{"class":67},[40,1767,1602],{"class":306},[40,1769,130],{"class":67},[40,1771,1772],{"class":107},"\u002F\u002F 42\n",[40,1774,1776,1778,1780,1782,1784],{"class":42,"line":1775},24,[40,1777,1698],{"class":50},[40,1779,124],{"class":67},[40,1781,1616],{"class":306},[40,1783,130],{"class":67},[40,1785,1786],{"class":107},"\u002F\u002F 49\n",[40,1788,1790,1792,1794,1796,1798],{"class":42,"line":1789},25,[40,1791,1698],{"class":50},[40,1793,124],{"class":67},[40,1795,1630],{"class":306},[40,1797,130],{"class":67},[40,1799,1800],{"class":107},"\u002F\u002F 56\n",[40,1802,1804,1806,1808,1810,1812],{"class":42,"line":1803},26,[40,1805,1698],{"class":50},[40,1807,124],{"class":67},[40,1809,1644],{"class":306},[40,1811,130],{"class":67},[40,1813,1814],{"class":107},"\u002F\u002F 63\n",[40,1816,1818,1820,1822,1824,1826],{"class":42,"line":1817},27,[40,1819,1698],{"class":50},[40,1821,124],{"class":67},[40,1823,1658],{"class":306},[40,1825,130],{"class":67},[40,1827,1828],{"class":107},"\u002F\u002F 70\n",[10,1830,1831,1832,1834,1835,1838,1839,1842,1843,117],{},"En este ejemplo, la función ",[37,1833,1481],{}," es una fábrica de funciones, ya que su ejecución crea nuevas funciones con\nalgunas ",[14,1836,1837],{},"\"configuraciones predeterminadas\""," que serán compartidas las veces que se ejecute la función, en este caso, la\n",[14,1840,1841],{},"\"configuración predeterminada\""," es lo que se envía como argumento al parámetro ",[37,1844,1427],{},[10,1846,1847,1848,1851,1852,1855,1856,1858,1859,1861,1862,1864,1865,1868,1869,1871,1872,1874,1875,117],{},"Como podemos ver, los ",[14,1849,1850],{},"entornos léxicos"," no se mezclan, si no que se crea uno cada vez que se guarda una nueva referencia de la\nfunción interna que forma el closure, y de esta forma manteniendo su independencia. De esta manera en la declaración\n",[37,1853,1854],{},"const _5x = crearTablaDeMultiplicar(5)",", en ",[14,1857,840],{}," de la función interna guarda el valor de ",[37,1860,1519],{},", que fue el que se le\nmandó como argumento al parámetro ",[37,1863,1427],{},", mientras que en la declaración ",[37,1866,1867],{},"const _7x = crearTablaDeMultiplicar(7)",", el\n",[14,1870,840],{}," guarda el valor de ",[37,1873,1616],{},", pues ese fue el valor que se envió como argumento al parámetro ",[37,1876,1427],{},[212,1878,1880],{"id":1879},"ejemplo-de-uso-con-html","Ejemplo de uso con HTML",[10,1882,1883],{},"Imaginemos que tenemos estos elementos HTML:",[30,1885,1889],{"className":1886,"code":1887,"language":1888,"meta":35,"style":35},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cbutton id=\"size-12\">12\u003C\u002Fbutton>\n\u003Cbutton id=\"size-14\">14\u003C\u002Fbutton>\n\u003Cbutton id=\"size-16\">16\u003C\u002Fbutton>\n","html",[37,1890,1891,1926,1954],{"__ignoreMap":35},[40,1892,1893,1896,1899,1902,1904,1907,1910,1912,1915,1918,1921,1923],{"class":42,"line":43},[40,1894,1895],{"class":54},"\u003C",[40,1897,1898],{"class":123},"button",[40,1900,1901],{"class":46}," id",[40,1903,303],{"class":54},[40,1905,1906],{"class":54},"\"",[40,1908,1909],{"class":77},"size-12",[40,1911,1906],{"class":54},[40,1913,1914],{"class":54},">",[40,1916,1917],{"class":67},"12",[40,1919,1920],{"class":54},"\u003C\u002F",[40,1922,1898],{"class":123},[40,1924,1925],{"class":54},">\n",[40,1927,1928,1930,1932,1934,1936,1938,1941,1943,1945,1948,1950,1952],{"class":42,"line":61},[40,1929,1895],{"class":54},[40,1931,1898],{"class":123},[40,1933,1901],{"class":46},[40,1935,303],{"class":54},[40,1937,1906],{"class":54},[40,1939,1940],{"class":77},"size-14",[40,1942,1906],{"class":54},[40,1944,1914],{"class":54},[40,1946,1947],{"class":67},"14",[40,1949,1920],{"class":54},[40,1951,1898],{"class":123},[40,1953,1925],{"class":54},[40,1955,1956,1958,1960,1962,1964,1966,1969,1971,1973,1976,1978,1980],{"class":42,"line":84},[40,1957,1895],{"class":54},[40,1959,1898],{"class":123},[40,1961,1901],{"class":46},[40,1963,303],{"class":54},[40,1965,1906],{"class":54},[40,1967,1968],{"class":77},"size-16",[40,1970,1906],{"class":54},[40,1972,1914],{"class":54},[40,1974,1975],{"class":67},"16",[40,1977,1920],{"class":54},[40,1979,1898],{"class":123},[40,1981,1925],{"class":54},[10,1983,1984],{},"La finalidad de estos botones es que al presionarlos cambien el tamaño de la fuente según corresponda, hay muchas formas en las que\npodríamos abordar este problema, sin embargo, en esta ocasión intentaremos resolverlo con closures, vemos el siguiente código:",[30,1986,1988],{"className":32,"code":1987,"language":34,"meta":35,"style":35},"function makeSizer(size) {\n  return function () {\n    document.body.style.fontSize = `${size}px`;\n  };\n}\n\nconst setSize12 = makeSizer(12);\nconst setSize14 = makeSizer(14);\nconst setSize16 = makeSizer(16);\n",[37,1989,1990,2006,2017,2056,2061,2065,2069,2088,2107],{"__ignoreMap":35},[40,1991,1992,1994,1997,1999,2002,2004],{"class":42,"line":43},[40,1993,47],{"class":46},[40,1995,1996],{"class":50}," makeSizer",[40,1998,124],{"class":54},[40,2000,2001],{"class":1426},"size",[40,2003,1430],{"class":54},[40,2005,58],{"class":54},[40,2007,2008,2010,2012,2015],{"class":42,"line":61},[40,2009,1051],{"class":316},[40,2011,1439],{"class":46},[40,2013,2014],{"class":54}," ()",[40,2016,58],{"class":54},[40,2018,2019,2022,2024,2027,2029,2032,2034,2037,2039,2042,2044,2047,2050,2053],{"class":42,"line":84},[40,2020,2021],{"class":67},"    document",[40,2023,117],{"class":54},[40,2025,2026],{"class":67},"body",[40,2028,117],{"class":54},[40,2030,2031],{"class":67},"style",[40,2033,117],{"class":54},[40,2035,2036],{"class":67},"fontSize",[40,2038,71],{"class":54},[40,2040,2041],{"class":54}," `${",[40,2043,2001],{"class":67},[40,2045,2046],{"class":54},"}",[40,2048,2049],{"class":77},"px",[40,2051,2052],{"class":54},"`",[40,2054,2055],{"class":54},";\n",[40,2057,2058],{"class":42,"line":91},[40,2059,2060],{"class":54},"  };\n",[40,2062,2063],{"class":42,"line":104},[40,2064,159],{"class":54},[40,2066,2067],{"class":42,"line":111},[40,2068,88],{"emptyLinePlaceholder":87},[40,2070,2071,2073,2076,2078,2080,2082,2084,2086],{"class":42,"line":136},[40,2072,222],{"class":46},[40,2074,2075],{"class":67}," setSize12 ",[40,2077,303],{"class":54},[40,2079,1996],{"class":50},[40,2081,124],{"class":67},[40,2083,1917],{"class":306},[40,2085,1430],{"class":67},[40,2087,2055],{"class":54},[40,2089,2090,2092,2095,2097,2099,2101,2103,2105],{"class":42,"line":142},[40,2091,222],{"class":46},[40,2093,2094],{"class":67}," setSize14 ",[40,2096,303],{"class":54},[40,2098,1996],{"class":50},[40,2100,124],{"class":67},[40,2102,1947],{"class":306},[40,2104,1430],{"class":67},[40,2106,2055],{"class":54},[40,2108,2109,2111,2114,2116,2118,2120,2122,2124],{"class":42,"line":147},[40,2110,222],{"class":46},[40,2112,2113],{"class":67}," setSize16 ",[40,2115,303],{"class":54},[40,2117,1996],{"class":50},[40,2119,124],{"class":67},[40,2121,1975],{"class":306},[40,2123,1430],{"class":67},[40,2125,2055],{"class":54},[10,2127,2128,2129,2132,2133,2135,2136,2139,2140,2142,2143,2145,2146,2148,2149,2152,2153,219,2156,2159,2160,219,2163,2166],{},"En la función ",[37,2130,2131],{},"makeSizer",", como podemos ver, se forma un closure, puesto que en la función interna se hace referencia al parámetro\n",[37,2134,2001],{}," que nos llega en la función padre. Con esto podemos ver que la función ",[37,2137,2138],{},"setSize12"," guarda en su ",[14,2141,840],{}," el valor\nde ",[37,2144,1917],{},", por lo que al ejecutar esta función el tamaño de fuente del ",[14,2147,2026],{}," se cambiará a ",[37,2150,2151],{},"12px",", lo mismo pasará con las funciones\n",[37,2154,2155],{},"setSize14",[37,2157,2158],{},"setSize16"," con los valores ",[37,2161,2162],{},"14px",[37,2164,2165],{},"16px"," respectivamente.",[10,2168,2169,2170,2173,2174,2177],{},"Ahora podemos ",[14,2171,2172],{},"\"bindear\""," estas funciones en los eventos ",[37,2175,2176],{},"onclick"," de los botones de la siguiente manera:",[30,2179,2181],{"className":32,"code":2180,"language":34,"meta":35,"style":35},"document.getElementById(\"size-12\").onclick = size12;\ndocument.getElementById(\"size-14\").onclick = size14;\ndocument.getElementById(\"size-16\").onclick = size16;\n",[37,2182,2183,2215,2244],{"__ignoreMap":35},[40,2184,2185,2188,2190,2193,2195,2197,2199,2201,2203,2205,2208,2210,2213],{"class":42,"line":43},[40,2186,2187],{"class":67},"document",[40,2189,117],{"class":54},[40,2191,2192],{"class":50},"getElementById",[40,2194,124],{"class":67},[40,2196,1906],{"class":54},[40,2198,1909],{"class":77},[40,2200,1906],{"class":54},[40,2202,1430],{"class":67},[40,2204,117],{"class":54},[40,2206,2207],{"class":67},"onclick ",[40,2209,303],{"class":54},[40,2211,2212],{"class":67}," size12",[40,2214,2055],{"class":54},[40,2216,2217,2219,2221,2223,2225,2227,2229,2231,2233,2235,2237,2239,2242],{"class":42,"line":61},[40,2218,2187],{"class":67},[40,2220,117],{"class":54},[40,2222,2192],{"class":50},[40,2224,124],{"class":67},[40,2226,1906],{"class":54},[40,2228,1940],{"class":77},[40,2230,1906],{"class":54},[40,2232,1430],{"class":67},[40,2234,117],{"class":54},[40,2236,2207],{"class":67},[40,2238,303],{"class":54},[40,2240,2241],{"class":67}," size14",[40,2243,2055],{"class":54},[40,2245,2246,2248,2250,2252,2254,2256,2258,2260,2262,2264,2266,2268,2271],{"class":42,"line":84},[40,2247,2187],{"class":67},[40,2249,117],{"class":54},[40,2251,2192],{"class":50},[40,2253,124],{"class":67},[40,2255,1906],{"class":54},[40,2257,1968],{"class":77},[40,2259,1906],{"class":54},[40,2261,1430],{"class":67},[40,2263,117],{"class":54},[40,2265,2207],{"class":67},[40,2267,303],{"class":54},[40,2269,2270],{"class":67}," size16",[40,2272,2055],{"class":54},[10,2274,2275],{},"En este ejemplo, las closures nos ayudaron a crear una fábrica de funciones y poder reutilizar nuestra lógica para distintos valores.",[212,2277,2279],{"id":2278},"propiedades-privadas-con-ayuda-de-closures","Propiedades privadas con ayuda de closures",[10,2281,2282],{},"En lenguajes cuyo paradigma es la programación orientada a objetos(POO), se pueden crear propiedades privadas, lo que significa que no\nse puede acceder a ellas más que dentro de la propia clase.",[10,2284,2285,2286,2289,2290,2293],{},"Antes de ES6 no existían las clases en JavaScript, una forma que se usaba como ",[14,2287,2288],{},"workaround"," es emular estas propiedades privadas\ncreando closures, un ejemplo lo podemos ver a continuación, este ejemplo usa el ",[14,2291,2292],{},"patrón de diseño de módulo",":",[30,2295,2297],{"className":32,"code":2296,"language":34,"meta":35,"style":35},"const counter = (function () {\n  let privateCounter = 0\n\n  const changeBy = (value) => {\n    privateCounter += value\n  }\n\n  return {\n    increment() {\n      changeBy(1)\n    },\n    decrement() {\n      changeBy(-1)\n    },\n    getCounter() {\n      return privateCounter\n    }\n  }\n})()\n\nconsole.log(counter.getCounter()) \u002F\u002F 0\ncounter.increment()\ncounter.increment()\ncounter.increment()\nconsole.log(counter.getCounter()) \u002F\u002F 3\ncounter.decrement()\nconsole.log(counter.getCounter()) \u002F\u002F 2\nconsole.log(counter.privateCounter) \u002F\u002F undefined\n",[37,2298,2299,2316,2328,2332,2354,2365,2369,2373,2379,2388,2399,2404,2413,2426,2430,2439,2447,2452,2456,2463,2467,2489,2501,2511,2521,2540,2551,2570],{"__ignoreMap":35},[40,2300,2301,2303,2306,2308,2310,2312,2314],{"class":42,"line":43},[40,2302,222],{"class":46},[40,2304,2305],{"class":67}," counter ",[40,2307,303],{"class":54},[40,2309,320],{"class":67},[40,2311,47],{"class":46},[40,2313,2014],{"class":54},[40,2315,58],{"class":54},[40,2317,2318,2320,2323,2325],{"class":42,"line":61},[40,2319,64],{"class":46},[40,2321,2322],{"class":67}," privateCounter",[40,2324,71],{"class":54},[40,2326,2327],{"class":306}," 0\n",[40,2329,2330],{"class":42,"line":84},[40,2331,88],{"emptyLinePlaceholder":87},[40,2333,2334,2337,2340,2342,2344,2347,2349,2352],{"class":42,"line":91},[40,2335,2336],{"class":46},"  const",[40,2338,2339],{"class":67}," changeBy",[40,2341,71],{"class":54},[40,2343,320],{"class":54},[40,2345,2346],{"class":1426},"value",[40,2348,1430],{"class":54},[40,2350,2351],{"class":46}," =>",[40,2353,58],{"class":54},[40,2355,2356,2359,2362],{"class":42,"line":104},[40,2357,2358],{"class":67},"    privateCounter",[40,2360,2361],{"class":54}," +=",[40,2363,2364],{"class":67}," value\n",[40,2366,2367],{"class":42,"line":111},[40,2368,139],{"class":54},[40,2370,2371],{"class":42,"line":136},[40,2372,88],{"emptyLinePlaceholder":87},[40,2374,2375,2377],{"class":42,"line":142},[40,2376,1051],{"class":316},[40,2378,58],{"class":54},[40,2380,2381,2384,2386],{"class":42,"line":147},[40,2382,2383],{"class":123},"    increment",[40,2385,55],{"class":54},[40,2387,58],{"class":54},[40,2389,2390,2393,2395,2397],{"class":42,"line":156},[40,2391,2392],{"class":50},"      changeBy",[40,2394,124],{"class":123},[40,2396,1535],{"class":306},[40,2398,1038],{"class":123},[40,2400,2401],{"class":42,"line":162},[40,2402,2403],{"class":54},"    },\n",[40,2405,2406,2409,2411],{"class":42,"line":167},[40,2407,2408],{"class":123},"    decrement",[40,2410,55],{"class":54},[40,2412,58],{"class":54},[40,2414,2415,2417,2419,2422,2424],{"class":42,"line":366},[40,2416,2392],{"class":50},[40,2418,124],{"class":123},[40,2420,2421],{"class":54},"-",[40,2423,1535],{"class":306},[40,2425,1038],{"class":123},[40,2427,2428],{"class":42,"line":371},[40,2429,2403],{"class":54},[40,2431,2432,2435,2437],{"class":42,"line":382},[40,2433,2434],{"class":123},"    getCounter",[40,2436,55],{"class":54},[40,2438,58],{"class":54},[40,2440,2441,2444],{"class":42,"line":387},[40,2442,2443],{"class":316},"      return",[40,2445,2446],{"class":67}," privateCounter\n",[40,2448,2449],{"class":42,"line":1358},[40,2450,2451],{"class":54},"    }\n",[40,2453,2454],{"class":42,"line":1363},[40,2455,139],{"class":54},[40,2457,2458,2460],{"class":42,"line":1369},[40,2459,2046],{"class":54},[40,2461,2462],{"class":67},")()\n",[40,2464,2465],{"class":42,"line":1375},[40,2466,88],{"emptyLinePlaceholder":87},[40,2468,2469,2471,2473,2475,2478,2480,2483,2486],{"class":42,"line":1381},[40,2470,263],{"class":67},[40,2472,117],{"class":54},[40,2474,120],{"class":50},[40,2476,2477],{"class":67},"(counter",[40,2479,117],{"class":54},[40,2481,2482],{"class":50},"getCounter",[40,2484,2485],{"class":67},"()) ",[40,2487,2488],{"class":107},"\u002F\u002F 0\n",[40,2490,2491,2494,2496,2499],{"class":42,"line":1387},[40,2492,2493],{"class":67},"counter",[40,2495,117],{"class":54},[40,2497,2498],{"class":50},"increment",[40,2500,153],{"class":67},[40,2502,2503,2505,2507,2509],{"class":42,"line":1761},[40,2504,2493],{"class":67},[40,2506,117],{"class":54},[40,2508,2498],{"class":50},[40,2510,153],{"class":67},[40,2512,2513,2515,2517,2519],{"class":42,"line":1775},[40,2514,2493],{"class":67},[40,2516,117],{"class":54},[40,2518,2498],{"class":50},[40,2520,153],{"class":67},[40,2522,2523,2525,2527,2529,2531,2533,2535,2537],{"class":42,"line":1789},[40,2524,263],{"class":67},[40,2526,117],{"class":54},[40,2528,120],{"class":50},[40,2530,2477],{"class":67},[40,2532,117],{"class":54},[40,2534,2482],{"class":50},[40,2536,2485],{"class":67},[40,2538,2539],{"class":107},"\u002F\u002F 3\n",[40,2541,2542,2544,2546,2549],{"class":42,"line":1803},[40,2543,2493],{"class":67},[40,2545,117],{"class":54},[40,2547,2548],{"class":50},"decrement",[40,2550,153],{"class":67},[40,2552,2553,2555,2557,2559,2561,2563,2565,2567],{"class":42,"line":1817},[40,2554,263],{"class":67},[40,2556,117],{"class":54},[40,2558,120],{"class":50},[40,2560,2477],{"class":67},[40,2562,117],{"class":54},[40,2564,2482],{"class":50},[40,2566,2485],{"class":67},[40,2568,2569],{"class":107},"\u002F\u002F 2\n",[40,2571,2573,2575,2577,2579,2581,2583,2586],{"class":42,"line":2572},28,[40,2574,263],{"class":67},[40,2576,117],{"class":54},[40,2578,120],{"class":50},[40,2580,2477],{"class":67},[40,2582,117],{"class":54},[40,2584,2585],{"class":67},"privateCounter) ",[40,2587,273],{"class":107},[10,2589,2590,2591,2594,2595,2597,2598,2601,2602,2605,2606,2609,2610,2613,2614,2616,2617,2619,2620,2622],{},"Como podemos observar, en este ejemplo estamos usando una IIFE(",[14,2592,2593],{},"Immediately Invoked Function Expression","), lo que hace que en la\nconstante ",[37,2596,2493],{}," se guarde ",[14,2599,2600],{},"\"en automático\""," lo que retorna esta función. Con este ejemplo podemos ver que realmente las closures\nno solo son ",[14,2603,2604],{},"\"funciones que retornan otras funciones...\"",", sino que como vemos, estamos retornando un objeto con distintos métodos\nque a través de las closures mantienen viva la referencia a la variable ",[37,2607,2608],{},"privateCounter"," y a la constante ",[37,2611,2612],{},"changeBy",", que a su vez\ninternamente crea también una closure con la variable ",[37,2615,2608],{}," y como podemos observar en la última línea, no podemos acceder\ndirectamente a ",[37,2618,2608],{},", sólo a través de la función ",[37,2621,2482],{},", así, emulamos comportamientos de la POO, como el\nencapsulamiento, con ayuda de las closures.",[212,2624,2626],{"id":2625},"closures-sobre-módulos","Closures sobre módulos",[10,2628,2629],{},"Las closures también pueden generarse en distintos módulos, por ejemplo veamos lo siguiente:",[30,2631,2634],{"className":32,"code":2632,"filename":2633,"language":34,"meta":35,"style":35},"let foo = 5\nexport const getFoo = () => foo\nexport const setFoo = (value) => {\n  foo = value\n}\n","fooModule.js",[37,2635,2636,2647,2667,2688,2697],{"__ignoreMap":35},[40,2637,2638,2640,2643,2645],{"class":42,"line":43},[40,2639,218],{"class":46},[40,2641,2642],{"class":67}," foo ",[40,2644,303],{"class":54},[40,2646,307],{"class":306},[40,2648,2649,2652,2655,2658,2660,2662,2664],{"class":42,"line":61},[40,2650,2651],{"class":316},"export",[40,2653,2654],{"class":46}," const",[40,2656,2657],{"class":67}," getFoo ",[40,2659,303],{"class":54},[40,2661,2014],{"class":54},[40,2663,2351],{"class":46},[40,2665,2666],{"class":67}," foo\n",[40,2668,2669,2671,2673,2676,2678,2680,2682,2684,2686],{"class":42,"line":84},[40,2670,2651],{"class":316},[40,2672,2654],{"class":46},[40,2674,2675],{"class":67}," setFoo ",[40,2677,303],{"class":54},[40,2679,320],{"class":54},[40,2681,2346],{"class":1426},[40,2683,1430],{"class":54},[40,2685,2351],{"class":46},[40,2687,58],{"class":54},[40,2689,2690,2693,2695],{"class":42,"line":91},[40,2691,2692],{"class":67},"  foo",[40,2694,71],{"class":54},[40,2696,2364],{"class":67},[40,2698,2699],{"class":42,"line":104},[40,2700,159],{"class":54},[10,2702,2703,2704,219,2707,2710,2711,2714,2715,2718,2719,2722,2723,2293],{},"Este módulo crea un par de funciones ",[14,2705,2706],{},"setter",[14,2708,2709],{},"getter"," sobre la variable ",[37,2712,2713],{},"foo",", lo que hace que aunque esta variable no sea\naccesible desde otros módulos, porque no está exportada, sí pueda ser alcanzada y modificada a través de las funciones ",[37,2716,2717],{},"getFoo"," y\n",[37,2720,2721],{},"setFoo",", que como podemos ver, han creado un closure con la variable ",[37,2724,2713],{},[30,2726,2729],{"className":32,"code":2727,"filename":2728,"language":34,"meta":35,"style":35},"import { getFoo, setFoo } from \".\u002FfooModule.js\"\n\nconsole.log(getFoo()) \u002F\u002F 5\nsetFoo(6)\nconsole.log(getFoo()) \u002F\u002F 6\n","main.js",[37,2730,2731,2763,2767,2783,2793],{"__ignoreMap":35},[40,2732,2733,2736,2739,2742,2745,2748,2751,2754,2757,2760],{"class":42,"line":43},[40,2734,2735],{"class":316},"import",[40,2737,2738],{"class":54}," {",[40,2740,2741],{"class":67}," getFoo",[40,2743,2744],{"class":54},",",[40,2746,2747],{"class":67}," setFoo",[40,2749,2750],{"class":54}," }",[40,2752,2753],{"class":316}," from",[40,2755,2756],{"class":54}," \"",[40,2758,2759],{"class":77},".\u002FfooModule.js",[40,2761,2762],{"class":54},"\"\n",[40,2764,2765],{"class":42,"line":61},[40,2766,88],{"emptyLinePlaceholder":87},[40,2768,2769,2771,2773,2775,2777,2779,2781],{"class":42,"line":84},[40,2770,263],{"class":67},[40,2772,117],{"class":54},[40,2774,120],{"class":50},[40,2776,124],{"class":67},[40,2778,2717],{"class":50},[40,2780,2485],{"class":67},[40,2782,359],{"class":107},[40,2784,2785,2787,2789,2791],{"class":42,"line":91},[40,2786,2721],{"class":50},[40,2788,124],{"class":67},[40,2790,1602],{"class":306},[40,2792,1038],{"class":67},[40,2794,2795,2797,2799,2801,2803,2805,2807],{"class":42,"line":104},[40,2796,263],{"class":67},[40,2798,117],{"class":54},[40,2800,120],{"class":50},[40,2802,124],{"class":67},[40,2804,2717],{"class":50},[40,2806,2485],{"class":67},[40,2808,2809],{"class":107},"\u002F\u002F 6\n",[10,2811,2812,2813,2816,2817,2820],{},"Las closures también pueden ser creadas sobre valores importados y que se consideren ",[14,2814,2815],{},"\"enlazados en vivo\"",", ya que al cambiar el\nvalor original cambia el valor importado en consecuencia, esto también es gracias a que los módulos en JavaScript se crean como un\n",[14,2818,2819],{},"singleton",", es decir, en todos los lugares donde se importe el módulo, realmente se estará usando la misma instancia del mismo,\nveamos el siguiente ejemplo para comprenderlo mejor:",[30,2822,2825],{"className":32,"code":2823,"filename":2824,"language":34,"meta":35,"style":35},"export let bar = 1\nexport const setBar = (value) => {\n  bar = value\n}\n","barModule.js",[37,2826,2827,2842,2863,2872],{"__ignoreMap":35},[40,2828,2829,2831,2834,2837,2839],{"class":42,"line":43},[40,2830,2651],{"class":316},[40,2832,2833],{"class":46}," let",[40,2835,2836],{"class":67}," bar ",[40,2838,303],{"class":54},[40,2840,2841],{"class":306}," 1\n",[40,2843,2844,2846,2848,2851,2853,2855,2857,2859,2861],{"class":42,"line":61},[40,2845,2651],{"class":316},[40,2847,2654],{"class":46},[40,2849,2850],{"class":67}," setBar ",[40,2852,303],{"class":54},[40,2854,320],{"class":54},[40,2856,2346],{"class":1426},[40,2858,1430],{"class":54},[40,2860,2351],{"class":46},[40,2862,58],{"class":54},[40,2864,2865,2868,2870],{"class":42,"line":84},[40,2866,2867],{"class":67},"  bar",[40,2869,71],{"class":54},[40,2871,2364],{"class":67},[40,2873,2874],{"class":42,"line":91},[40,2875,159],{"class":54},[30,2877,2880],{"className":32,"code":2878,"filename":2879,"language":34,"meta":35,"style":35},"import { bar } from \".\u002FbarModule.js\"\n\n\u002F\u002F Se crea el closure sobre un enlace en vivo importado\nexport const getBar = () => bar \n","closureCreator.js",[37,2881,2882,2902,2906,2911],{"__ignoreMap":35},[40,2883,2884,2886,2888,2891,2893,2895,2897,2900],{"class":42,"line":43},[40,2885,2735],{"class":316},[40,2887,2738],{"class":54},[40,2889,2890],{"class":67}," bar",[40,2892,2750],{"class":54},[40,2894,2753],{"class":316},[40,2896,2756],{"class":54},[40,2898,2899],{"class":77},".\u002FbarModule.js",[40,2901,2762],{"class":54},[40,2903,2904],{"class":42,"line":61},[40,2905,88],{"emptyLinePlaceholder":87},[40,2907,2908],{"class":42,"line":84},[40,2909,2910],{"class":107},"\u002F\u002F Se crea el closure sobre un enlace en vivo importado\n",[40,2912,2913,2915,2917,2920,2922,2924,2926],{"class":42,"line":91},[40,2914,2651],{"class":316},[40,2916,2654],{"class":46},[40,2918,2919],{"class":67}," getBar ",[40,2921,303],{"class":54},[40,2923,2014],{"class":54},[40,2925,2351],{"class":46},[40,2927,2928],{"class":67}," bar\n",[30,2930,2933],{"className":32,"code":2931,"filename":2932,"language":34,"meta":35,"style":35},"import { getBar } from \".\u002FclosureCreator.js\"\nimport { setBar } from \".\u002FbarModule.js\"\n\nconsole.log(getBar()) \u002F\u002F 1\nsetBar(2);\nconsole.log(getBar()) \u002F\u002F 2\n","index.js",[37,2934,2935,2955,2974,2978,2996,3009],{"__ignoreMap":35},[40,2936,2937,2939,2941,2944,2946,2948,2950,2953],{"class":42,"line":43},[40,2938,2735],{"class":316},[40,2940,2738],{"class":54},[40,2942,2943],{"class":67}," getBar",[40,2945,2750],{"class":54},[40,2947,2753],{"class":316},[40,2949,2756],{"class":54},[40,2951,2952],{"class":77},".\u002FclosureCreator.js",[40,2954,2762],{"class":54},[40,2956,2957,2959,2961,2964,2966,2968,2970,2972],{"class":42,"line":61},[40,2958,2735],{"class":316},[40,2960,2738],{"class":54},[40,2962,2963],{"class":67}," setBar",[40,2965,2750],{"class":54},[40,2967,2753],{"class":316},[40,2969,2756],{"class":54},[40,2971,2899],{"class":77},[40,2973,2762],{"class":54},[40,2975,2976],{"class":42,"line":84},[40,2977,88],{"emptyLinePlaceholder":87},[40,2979,2980,2982,2984,2986,2988,2991,2993],{"class":42,"line":91},[40,2981,263],{"class":67},[40,2983,117],{"class":54},[40,2985,120],{"class":50},[40,2987,124],{"class":67},[40,2989,2990],{"class":50},"getBar",[40,2992,2485],{"class":67},[40,2994,2995],{"class":107},"\u002F\u002F 1\n",[40,2997,2998,3001,3003,3005,3007],{"class":42,"line":104},[40,2999,3000],{"class":50},"setBar",[40,3002,124],{"class":67},[40,3004,1548],{"class":306},[40,3006,1430],{"class":67},[40,3008,2055],{"class":54},[40,3010,3011,3013,3015,3017,3019,3021,3023],{"class":42,"line":111},[40,3012,263],{"class":67},[40,3014,117],{"class":54},[40,3016,120],{"class":50},[40,3018,124],{"class":67},[40,3020,2990],{"class":50},[40,3022,2485],{"class":67},[40,3024,2569],{"class":107},[10,3026,3027,3028,3031,3032,3034,3035,3037,3038,3040,3041,3043,3044,3046,3047,3049,3050,3052,3053,3055,3056,3058],{},"En este ejemplo vemos que la variable ",[37,3029,3030],{},"bar"," se crea en ",[37,3033,2824],{},", y en este mismo módulo se exporta la función ",[37,3036,3000],{}," para\npoder cambiar su valor; en el módulo ",[37,3039,2879],{}," se crea el closure dentro de la función ",[37,3042,2990],{}," y estas dos funciones\nexportadas por módulos distintos pueden ser usadas en un tercer módulo ",[37,3045,2932],{},", y al modificar la variable con la función ",[37,3048,3000],{},"\ny volver a ejecutar la función ",[37,3051,2990],{},", podemos ver que el valor original de ",[37,3054,3030],{}," ha cambiado y la función ",[37,3057,2990],{}," tiene acceso\nal nuevo valor actualizado.",[22,3060,3062],{"id":3061},"cadena-de-alcance-de-las-closures","Cadena de alcance de las closures",[10,3064,3065,3066,3068,3069,3071],{},"Gracias al ",[14,3067,840],{}," que existe dentro de cada función cada vez que se crea una, los bloques anidados pueden acceder hasta\nlas variables que estén en ",[14,3070,1850],{}," de niveles superiores, miremos el siguiente ejemplo:",[30,3073,3075],{"className":32,"code":3074,"language":34,"meta":35,"style":35},"const globalValue = 10\n\nfunction padre() {\n  return function hija() {\n    console.log(globalValue)\n  }\n}\n\npadre()() \u002F\u002F 10\n",[37,3076,3077,3088,3092,3102,3115,3130,3134,3138,3142],{"__ignoreMap":35},[40,3078,3079,3081,3084,3086],{"class":42,"line":43},[40,3080,222],{"class":46},[40,3082,3083],{"class":67}," globalValue ",[40,3085,303],{"class":54},[40,3087,379],{"class":306},[40,3089,3090],{"class":42,"line":61},[40,3091,88],{"emptyLinePlaceholder":87},[40,3093,3094,3096,3098,3100],{"class":42,"line":84},[40,3095,47],{"class":46},[40,3097,51],{"class":50},[40,3099,55],{"class":54},[40,3101,58],{"class":54},[40,3103,3104,3106,3108,3111,3113],{"class":42,"line":91},[40,3105,1051],{"class":316},[40,3107,1439],{"class":46},[40,3109,3110],{"class":50}," hija",[40,3112,55],{"class":54},[40,3114,58],{"class":54},[40,3116,3117,3119,3121,3123,3125,3128],{"class":42,"line":104},[40,3118,114],{"class":67},[40,3120,117],{"class":54},[40,3122,120],{"class":50},[40,3124,124],{"class":123},[40,3126,3127],{"class":67},"globalValue",[40,3129,1038],{"class":123},[40,3131,3132],{"class":42,"line":111},[40,3133,139],{"class":54},[40,3135,3136],{"class":42,"line":136},[40,3137,159],{"class":54},[40,3139,3140],{"class":42,"line":142},[40,3141,88],{"emptyLinePlaceholder":87},[40,3143,3144,3146,3149],{"class":42,"line":147},[40,3145,170],{"class":50},[40,3147,3148],{"class":67},"()() ",[40,3150,398],{"class":107},[10,3152,3153],{},"Lo que pasa en este ejemplo es lo siguiente:",[820,3155,3156,3164,3183,3209],{},[823,3157,1173,3158,3160,3161,3163],{},[37,3159,3127],{}," en el ",[14,3162,840],{}," global.",[823,3165,1165,3166,2139,3168,3170,3171,3174,3175,3177,3178,3180,3181,3163],{},[37,3167,170],{},[14,3169,840],{}," dos cosas, el ",[14,3172,3173],{},"registro de entorno","(que en este caso está vacío porque no hay\nvariables ni parámetros locales de la función ",[37,3176,170],{},") y la referencia al ",[14,3179,840],{}," externo, que en este caso es el\n",[14,3182,840],{},[823,3184,1139,3185,3187,3188,3191,3192,3194,3195,3197,3198,3200,3201,3203,3204,3206,3207,117],{},[37,3186,170],{}," se crea una nueva función, la función ",[37,3189,3190],{},"hija",", esta función también tiene su propio ",[14,3193,840],{},",\nque al igual que la función ",[37,3196,170],{},", tiene el ",[14,3199,3173],{},", que también está vacío al no haber variables ni parámetros\nen el ámbito local de la función ",[37,3202,3190],{},", y la referencia al ",[14,3205,840],{}," superior, que es el de la función ",[37,3208,170],{},[823,3210,1139,3211,3213,3214,3216,3217],{},[37,3212,3190],{}," se intente leer la variable ",[37,3215,3127],{},":\n",[820,3218,3219,3235,3253],{},[823,3220,3221,3222,3224,3225,3227,3228,3230,3231,1202,3233,117],{},"JavaScript primero mira en el ",[14,3223,3173],{}," de la propia función ",[37,3226,3190],{},", como no la encuentra, usa la referencia externa\nguardada dentro de su ",[14,3229,840],{}," para acceder al ",[14,3232,840],{},[37,3234,170],{},[823,3236,3237,3238,3160,3240,1202,3242,3244,3245,1202,3247,3249,3250,117],{},"Busca la variable ",[37,3239,3127],{},[14,3241,3173],{},[37,3243,170],{}," pero tampoco la encuentra ahí, así que usa la\nreferencia externa que tiene el ",[14,3246,840],{},[37,3248,170],{}," para acceder al siguiente nivel, que en nuestro ejemplo\nes el ",[14,3251,3252],{},"entorno léxico global",[823,3254,3255,3256,3258,3259,3261,3262,3265,3266,3268,3269,3271],{},"Al llegar al ",[14,3257,3252],{},", busca en el ",[14,3260,3173],{}," de este ",[14,3263,3264],{},"entono léxico"," la variable ",[37,3267,3127],{},", en\neste ",[14,3270,3173],{}," sí existe, por lo que accede a ela, lee su valor y opera con el mismo, en nuestro ejemplo simplemente\nmuestra el valor guardado en la consola.",[10,3273,3274,3275,3278,3279,3282],{},"Es de esta manera como las funciones o bloques que están muy anidados pueden llegar a leer variables que se encuentren en\n",[14,3276,3277],{},"registros de entorno"," de niveles superiores. Un modelo mental que podemos tener al momento de intentar entender este comportamiento\nes mirarlo como una lista simplemente enlazada(",[14,3280,3281],{},"single linked list","), cuyos valores se van enlazando desde el bloque más anidado\nhasta el de nivel superior.",[10,3284,3285],{},"Algo que me ayudó a comprender cómo estos valores se van enlazando es viéndolo de la siguiente manera, en nuestro ejemplo:",[30,3287,3289],{"className":32,"code":3288,"language":34,"meta":35,"style":35},"const entornoLexicoDeFuncionHija = {\n  \u002F\u002F vacío porque no hay variables ni parámetros declarados en la función hija\n  registroDeEntorno: {},\n\n  \u002F\u002F referencia al entorno léxico de la función padre\n  referenciaExterna: {\n    \u002F\u002F vacío porque no hay variables ni parámetros declarados en la función padre\n    registroDeEntorno: {},\n\n    \u002F\u002F referencia al entorno léxico global\n    referenciaExterna: {\n      \u002F\u002F en este entorno léxico si está declarada la variable globalValue\n      registroDeEntorno: {\n        globalValue: 10\n      },\n\n      referenciaExterna: null \u002F\u002F ya no hay porque este es el entorno léxico global\n    }\n  }\n}\n",[37,3290,3291,3302,3307,3317,3321,3326,3335,3340,3349,3353,3358,3367,3372,3381,3390,3395,3399,3412,3416,3420],{"__ignoreMap":35},[40,3292,3293,3295,3298,3300],{"class":42,"line":43},[40,3294,222],{"class":46},[40,3296,3297],{"class":67}," entornoLexicoDeFuncionHija ",[40,3299,303],{"class":54},[40,3301,58],{"class":54},[40,3303,3304],{"class":42,"line":61},[40,3305,3306],{"class":107},"  \u002F\u002F vacío porque no hay variables ni parámetros declarados en la función hija\n",[40,3308,3309,3312,3314],{"class":42,"line":84},[40,3310,3311],{"class":123},"  registroDeEntorno",[40,3313,2293],{"class":54},[40,3315,3316],{"class":54}," {},\n",[40,3318,3319],{"class":42,"line":91},[40,3320,88],{"emptyLinePlaceholder":87},[40,3322,3323],{"class":42,"line":104},[40,3324,3325],{"class":107},"  \u002F\u002F referencia al entorno léxico de la función padre\n",[40,3327,3328,3331,3333],{"class":42,"line":111},[40,3329,3330],{"class":123},"  referenciaExterna",[40,3332,2293],{"class":54},[40,3334,58],{"class":54},[40,3336,3337],{"class":42,"line":136},[40,3338,3339],{"class":107},"    \u002F\u002F vacío porque no hay variables ni parámetros declarados en la función padre\n",[40,3341,3342,3345,3347],{"class":42,"line":142},[40,3343,3344],{"class":123},"    registroDeEntorno",[40,3346,2293],{"class":54},[40,3348,3316],{"class":54},[40,3350,3351],{"class":42,"line":147},[40,3352,88],{"emptyLinePlaceholder":87},[40,3354,3355],{"class":42,"line":156},[40,3356,3357],{"class":107},"    \u002F\u002F referencia al entorno léxico global\n",[40,3359,3360,3363,3365],{"class":42,"line":162},[40,3361,3362],{"class":123},"    referenciaExterna",[40,3364,2293],{"class":54},[40,3366,58],{"class":54},[40,3368,3369],{"class":42,"line":167},[40,3370,3371],{"class":107},"      \u002F\u002F en este entorno léxico si está declarada la variable globalValue\n",[40,3373,3374,3377,3379],{"class":42,"line":366},[40,3375,3376],{"class":123},"      registroDeEntorno",[40,3378,2293],{"class":54},[40,3380,58],{"class":54},[40,3382,3383,3386,3388],{"class":42,"line":371},[40,3384,3385],{"class":123},"        globalValue",[40,3387,2293],{"class":54},[40,3389,379],{"class":306},[40,3391,3392],{"class":42,"line":382},[40,3393,3394],{"class":54},"      },\n",[40,3396,3397],{"class":42,"line":387},[40,3398,88],{"emptyLinePlaceholder":87},[40,3400,3401,3404,3406,3409],{"class":42,"line":1358},[40,3402,3403],{"class":123},"      referenciaExterna",[40,3405,2293],{"class":54},[40,3407,3408],{"class":54}," null",[40,3410,3411],{"class":107}," \u002F\u002F ya no hay porque este es el entorno léxico global\n",[40,3413,3414],{"class":42,"line":1363},[40,3415,2451],{"class":54},[40,3417,3418],{"class":42,"line":1369},[40,3419,139],{"class":54},[40,3421,3422],{"class":42,"line":1375},[40,3423,159],{"class":54},[10,3425,3426,3427,3429],{},"Aunque esto es un resumen muy abstracto de cómo se van enlazando los ",[14,3428,1850],{},", puede ayudarnos a comprender cómo es que\ndesde funciones o bloques muy anidados JavaScript puede acceder a variables de entornos superiores.",[10,3431,3432],{},"De manera general y resumida podemos decir que cada bloque tiene 3 alcances:",[820,3434,3435,3438,3443],{},[823,3436,3437],{},"El alcance local (Registro de Entorno)",[823,3439,3440,3441,1430],{},"El alcance adyacente o envolvente (a través de las referencias externas del ",[14,3442,840],{},[823,3444,3445,3446,3448],{},"El alcance global (gracias a los enlaces que existen en los ",[14,3447,1850],{}," adyacentes)",[10,3450,3451],{},"Esto mismo es lo que pasa cuando tenemos muchas closures anidadas de la siguiente manera:",[30,3453,3455],{"className":32,"code":3454,"language":34,"meta":35,"style":35},"const e = 10\n\nfunction sum(a) {\n  return function sum1(b) {\n    return function sum2(c) {\n      return function sum3(d) {\n        return a + b + c + d + e\n      }\n    }\n  } \n}\n\nconsole.log(suma(1)(2)(3)(4)) \u002F\u002F 20\n",[37,3456,3457,3468,3472,3488,3506,3525,3543,3572,3577,3581,3589,3593,3597],{"__ignoreMap":35},[40,3458,3459,3461,3464,3466],{"class":42,"line":43},[40,3460,222],{"class":46},[40,3462,3463],{"class":67}," e ",[40,3465,303],{"class":54},[40,3467,379],{"class":306},[40,3469,3470],{"class":42,"line":61},[40,3471,88],{"emptyLinePlaceholder":87},[40,3473,3474,3476,3479,3481,3484,3486],{"class":42,"line":84},[40,3475,47],{"class":46},[40,3477,3478],{"class":50}," sum",[40,3480,124],{"class":54},[40,3482,3483],{"class":1426},"a",[40,3485,1430],{"class":54},[40,3487,58],{"class":54},[40,3489,3490,3492,3494,3497,3499,3502,3504],{"class":42,"line":91},[40,3491,1051],{"class":316},[40,3493,1439],{"class":46},[40,3495,3496],{"class":50}," sum1",[40,3498,124],{"class":54},[40,3500,3501],{"class":1426},"b",[40,3503,1430],{"class":54},[40,3505,58],{"class":54},[40,3507,3508,3511,3513,3516,3518,3521,3523],{"class":42,"line":104},[40,3509,3510],{"class":316},"    return",[40,3512,1439],{"class":46},[40,3514,3515],{"class":50}," sum2",[40,3517,124],{"class":54},[40,3519,3520],{"class":1426},"c",[40,3522,1430],{"class":54},[40,3524,58],{"class":54},[40,3526,3527,3529,3531,3534,3536,3539,3541],{"class":42,"line":111},[40,3528,2443],{"class":316},[40,3530,1439],{"class":46},[40,3532,3533],{"class":50}," sum3",[40,3535,124],{"class":54},[40,3537,3538],{"class":1426},"d",[40,3540,1430],{"class":54},[40,3542,58],{"class":54},[40,3544,3545,3548,3551,3554,3557,3559,3562,3564,3567,3569],{"class":42,"line":136},[40,3546,3547],{"class":316},"        return",[40,3549,3550],{"class":67}," a",[40,3552,3553],{"class":54}," +",[40,3555,3556],{"class":67}," b",[40,3558,3553],{"class":54},[40,3560,3561],{"class":67}," c",[40,3563,3553],{"class":54},[40,3565,3566],{"class":67}," d",[40,3568,3553],{"class":54},[40,3570,3571],{"class":67}," e\n",[40,3573,3574],{"class":42,"line":142},[40,3575,3576],{"class":54},"      }\n",[40,3578,3579],{"class":42,"line":147},[40,3580,2451],{"class":54},[40,3582,3583,3586],{"class":42,"line":156},[40,3584,3585],{"class":54},"  }",[40,3587,3588],{"class":123}," \n",[40,3590,3591],{"class":42,"line":162},[40,3592,159],{"class":54},[40,3594,3595],{"class":42,"line":167},[40,3596,88],{"emptyLinePlaceholder":87},[40,3598,3599,3601,3603,3605,3607,3610,3612,3614,3617,3619,3621,3623,3625,3627,3630],{"class":42,"line":366},[40,3600,263],{"class":67},[40,3602,117],{"class":54},[40,3604,120],{"class":50},[40,3606,124],{"class":67},[40,3608,3609],{"class":50},"suma",[40,3611,124],{"class":67},[40,3613,1535],{"class":306},[40,3615,3616],{"class":67},")(",[40,3618,1548],{"class":306},[40,3620,3616],{"class":67},[40,3622,1561],{"class":306},[40,3624,3616],{"class":67},[40,3626,1575],{"class":306},[40,3628,3629],{"class":67},")) ",[40,3631,1580],{"class":107},[10,3633,3634,3635,3637,3638,3641,3642,3644,3645,3644,3647,3644,3649,219,3651,3654,3655,3660],{},"Gracias a los ",[14,3636,1850],{}," enlazados es que la función ",[37,3639,3640],{},"sum3"," puede acceder y leer todos los valores de ",[37,3643,3483],{},", ",[37,3646,3501],{},[37,3648,3520],{},[37,3650,3538],{},[37,3652,3653],{},"e",",\na esto es a lo que se conoce como ",[14,3656,3657],{},[196,3658,3659],{},"cadena de alcance de las closures",", lo cual ahora ya sabemos por qué funciona.",[10,3662,3663,3664,3667,3668,3673],{},"Como dato adicional, la expresión que escribimos en el ejemplo anterior ",[37,3665,3666],{},"suma(1)(2)(3)(4)"," está usando una técnica que se llama\n",[14,3669,3670],{},[196,3671,3672],{},"Currying",", la cual, en JavaScript, también depende de las closures para poder funcionar.",[22,3675,3677],{"id":3676},"recomendaciones-y-buenas-prácticas-al-usar-closures","Recomendaciones y buenas prácticas al usar closures",[10,3679,3680],{},"Aunque las closures son una característica poderosa y nos pueden ayudar a resolver varios problemas, es necesario tener en cuenta\nalgunas recomendaciones y buenas prácticas al usarlas, recuerda, un gran poder conlleva una gran responsabilidad.",[820,3682,3683,3689,3701,3707],{},[823,3684,3685,3688],{},[196,3686,3687],{},"Privatizar datos y variables",": Usa closures para ocultar variables del alcance global. Esto evita que otros scripts modifiquen\ntus datos accidentalmente. Define variables dentro de una función y expón solo los métodos para interactuar con ellas.",[823,3690,3691,3694,3695,568,3698,3700],{},[196,3692,3693],{},"Evitar fugas de memoria(Memory Leaks)",": Los closures mantienen vivas las variables de su entorno externo, lo que puede impedir\nque el recolector de basura libere esa memoria. Limpia las referencias asignando ",[37,3696,3697],{},"null",[37,3699,491],{}," a las variables o funciones\nque ya no vayas a utilizar.",[823,3702,3703,3706],{},[196,3704,3705],{},"Crear fábricas de funciones(Factory Functions)",": Aprovecha los closures para generar funciones personalizadas basadas en\nargumentos iniciales. Esto promueve la reutilización de código. Pasa un parámetro a la función principal para configurar el entorno\ny retorna una nueva función adaptada.",[823,3708,3709,3712],{},[196,3710,3711],{},"Mantener la legibilidad y evitar el abuso",": Anidar demasiados closures puede hacer que el código sea difícil de leer, depurar\ny mantener. Usa closures cuando aporten un beneficio claro(como el encapsulamiento), no por defecto en cada función.",[22,3714,3716],{"id":3715},"cierre","Cierre",[10,3718,3719],{},"Ahora ya conoces realmente lo que son las closures y cómo funciona a más bajo nivel esta característica del lenguaje JavaScript, sin\nembargo, no significa que ahora tengas que usar closures en todas partes, siempre ten en mente que cada nuevo concepto que aprendemos\nes una herramienta nueva que agregamos a nuestro arsenal, de esta manera, cuando estemos resolviendo un problema sepamos que esa\nherramienta existe y podemos hacer uso de ella para llegar a algunas soluciones si es necesario, aunque también siempre recuerda que\nes nuestra labor y responsabilidad como ingenieros de software saber cuando sí usar una herramienta y cuando no, así como las\nventajas y desventajas frente a otras posibles soluciones con otras herramientas distintas.",[10,3721,3722],{},"Espero que este artículo te haya gustado y hayas aprendido algo nuevo, sin más me despido, nos vemos en la próxima entrega.",[2031,3724,3725],{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":35,"searchDepth":61,"depth":61,"links":3727},[3728,3733,3734,3740,3741,3742],{"id":24,"depth":61,"text":25,"children":3729},[3730,3732],{"id":214,"depth":84,"text":3731},"Alcance con let y const",{"id":771,"depth":84,"text":772},{"id":859,"depth":61,"text":860},{"id":1398,"depth":61,"text":1399,"children":3735},[3736,3737,3738,3739],{"id":1405,"depth":84,"text":1406},{"id":1879,"depth":84,"text":1880},{"id":2278,"depth":84,"text":2279},{"id":2625,"depth":84,"text":2626},{"id":3061,"depth":61,"text":3062},{"id":3676,"depth":61,"text":3677},{"id":3715,"depth":61,"text":3716},[3744],"javascript","Aprende qué son las closures y otros conceptos del lenguaje JavaScript que hacen posibles su funcionamiento.","md","\u002Fr2\u002Fimages\u002Fblog\u002F02-closures-a-fondo-en-js.webp",{},"\u002Fblog\u002Fclosures-a-fondo-en-javascript","2026-09-07T00:00:00-06:00","---\ntitle: Closures a fondo en JavaScript\ndescription: Aprende qué son las closures y otros conceptos del lenguaje JavaScript que hacen posibles su funcionamiento.\npubDate: 2026-09-07T00:00:00-06:00\nimage: \u002Fr2\u002Fimages\u002Fblog\u002F02-closures-a-fondo-en-js.webp\nminRead: 20\ncategories:\n  - javascript\n---\n\n\u003C!-- cspell:ignore funcionHijo entornoLexicoDeFuncionHija -->\n\nCuando comencé a aprender sobre las closures, escuché y leí muchas veces explicaciones como esta: *\"Una closure es una función\nque retorna otra función, y la función que se retorna usa variables que se definieron en el cuerpo de la función padre\"*, o\nvarias explicaciones que prácticamente se referían a algo similar a esta definición, y aunque en el escenario que se expone en\nesta definición se forma una closure, la definición como tal no es 100% correcta y hay muchas otras cosas que podemos aprender\npara profundizar en el uso y comportamiento de las closures.\n\nEn este artículo exploramos a fondo qué son las closures, así como otros conceptos del lenguaje JavaScript, como el entorno léxico,\nque nos ayudarán a comprender el funcionamiento interno de las mismas. Aprenderemos cómo es que estos conceptos se relacionan\ndirectamente con los alcances de bloque(scopes) introducidos en la especificación ECMAScript 6, así como la relación que tienen\ncon las closures, y cómo el entender estos mecanismos nos ayudarán a comprender cómo es que al usar closures se pueden mantener\n\"vivas\" variables, constantes, parámetros y demás dentro de su alcance, incluso cuando la función donde fueron creadas hayan\nterminado su ejecución. Si te interesa conocer todo esto te invito a leer hasta al final porque hay mucha información interesante y\nseguro que algo nuevo aprendes hoy.\n\n\n## ¿Qué son las closures?\n\nUn closure es la combinación de una función agrupada dentro de otra con referencias a su estado adyacente. Veamos el siguiente\nejemplo para entenderlo un poco mejor:\n\n``` js\nfunction padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n\t  \u002F\u002F hijo es la función interna que forma el closure\n    console.log(nombre) \u002F\u002F Podemos acceder a la variable nombre\n  }\n\n  hijo()\n}\n\npadre() \u002F\u002F Se muestra en la consola 'pemid'\n```\n\nEn este ejemplo podemos ver que en la función `hijo` se lee la variable declarada en la función `padre`, prácticamente, en este\nejemplo la closure se crea entre al función `hijo` y la variable declarada en la función `padre`. Si has programado con JavaScript\no TypeScript durante un tiempo te habrás percatado de que realmente esto se relaciona directamente con otro concepto que también\nes muy importante desde inicio que es el ***scope*** o alcance, y esto mismo se relaciona con los conceptos de ***Ámbito Léxico***\ny ***Entorno Léxico***.\n\n\n### Alcance con `let` y `const`\n\nAntes de conocer lo que son el Ámbito Léxico y el Entorno Léxico, conozcamos el contexto en que estos conceptos fueron concebidos\nen JavaScript. En JavaScript tradicional, antes de la llegada de la especificación ECMAScript 6(ES6), las variables eran declaradas\ncon la palabra reservada `var`, con estas variables, JavaScript hacia un proceso de ***hoisting***, el cual *\"elevaba\"* la\ndeclaración de las variables al inicio de la ejecución del archivo o módulo, lo cual hacía que pudieras usarlas incluso antes de su\ndeclaración o inicialización explícita, tal y como se muestra en el siguiente ejemplo:\n\n``` js\nvar x \u002F\u002F declarada, inicializada con undefined\n\nconsole.log(x) \u002F\u002F undefined\nconsole.log(y) \u002F\u002F undefined\n\u002F\u002F la variable \"y\" se puede usar antes de su declaración debido al proceso de hoisting \n\nx = 5\n\nif (true) {\n  var y \u002F\u002F Declarada, \"hoisteada\" e inicializada en undefined\n  console.log(x) \u002F\u002F 5\n}\n\ny = 10\n\nconsole.log(y) \u002F\u002F 10\n```\n\nEsto como te puedes imaginar, podía causar bugs muy complicados de encontrar. Con la llegada de ES6, JavaScript introdujo nuevas\nformas de declarar variables y constantes, esto como sabemos es con las palabras reservadas `let` y `const`, con esto llegaron\nnuevos conceptos, entre los cuales están las ***Temporal Dead Zones(TDZ)*** o zonas muertas temporales, y los ***scopes*** o\nalcances de bloque.\n\nLa TDZ es la zona entre el inicio del bloque y la declaración de una variable, la cual prácticamente solo la vemos cuando declaramos\nuna variable con `let`, ya que al momento de declarar una constante con `const` debemos obligatoriamente inicializarlas con un\nvalor. Gracias a esto, si intentamos hacer algo parecido a nuestro ejemplo anterior, pero ahora declarando la variable con `let` en\nlugar de `var`, tendremos el siguiente error:\n\n``` js\nconsole.log(x) \u002F\u002F ReferenceError: Cannot access 'x' before initialization\n\nlet x\n\nx = 5\n```\n\nGracias a la TDZ, ahora si intentamos usar una variable antes de su declaración tendremos este error de\n***`Reference Error: cannot access 'x' before initialization`***. Es importante que sepamos que la TDZ solo es un mecanismo que\nhace que no se pueda acceder a una variable antes de su declaración, mas no de su inicialización, puesto que como ocurre con las\nvariables declaradas con `var`, si podemos acceder a ellas incluso antes de su inicialización ya que también JavaScript las\ninicializa en `undefined` como se muestra a continuación:\n\n``` js\nlet x\n\nconsole.log(x) \u002F\u002F undefined\n\nx = 5\n\nconsole.log(x) \u002F\u002F 5\n```\n\nOtro concepto importante que llegó junto con ES6 es el ***scope*** o alcance por bloque. Como vimos en nuestro ejemplo usando `var`,\nla variable `y`, declarada dentro de un bloque, podía ser accedida desde fuera de las llaves --las llaves delimitan el bloque(este\ncomportamiento sigue existiendo en JavaScript moderno, por eso ya no se recomienda declarar variables con `var`). El alcance por\nbloque se refiere a que las variables o constantes declaradas con `let` o `const`, solo pueden ser leídas en el mismo bloque o en\nbloques adyacentes *\"hijos\"*, pero las variables declaradas en bloques *\"hijos\"* no pueden ser leídas o accedidas desde bloques\n*\"padres\"* o superiores, veamos el siguiente ejemplo para enterderlo mejor:\n\n``` js\nlet var1 = 'outer'\n\nif (true) {\n  let var2 = 'inner'\n  console.log(var1) \u002F\u002F 'outer'\n  console.log(var2) \u002F\u002F 'inner'\n}\n\nconsole.log(var1) \u002F\u002F 'outer'\nconsole.log(var2) \u002F\u002F ReferenceError: var2 is not defined\n```\n\nEn este último ejemplo, la variable `var1` puede ser accedida desde el bloque del `if` puesto que es una variable que se declaró\nen un bloque *\"padre\"*(también se puede decir que se declaró en el ámbito externo), sin embargo como vemos al final, cuando\nintentamos acceder a `var2`, que está declarada dentro del bloque *\"hijo\"*(dentro de las llaves del `if`), JavaScript nos arroja\nun *ReferenceError*, pues como mencionamos antes, los bloques *\"padre\"* no pueden acceder a las variables declaradas en los bloques\n(o ámbitos) *\"hijo\"*.\n\nCon esto, ahora los bloques en JavaScript crean ámbitos o *scopes*, como lo vimos en este último ejemplo, el alcance de la variable\n`var2`, sólo es dentro del bloque entre las llaves de la sentencia `if`, por este comportamiento llegaron otros conceptos nuevos que\ndebemos conocer para comprender a fondo las closures, los cuales son el ***Ámbito\u002FAlcance Léxico***(o *lexical scope*) y el\n***Entorno Léxico***(o *lexical environment*).\n\n\n### Ámbito Léxico y Entorno Léxico\n\nCon la llegada de `let` y `const` en ES6, como mencionamos, los bloques crean *scopes*, con esto, podemos definir el\n***Ámbito Léxico*** como un concepto o regla del lenguaje JavaScript que determina la visibilidad y accesibilidad de las variables\nsegún donde se escribieron *\"físicamente\"* en el código; por otro lado, el ***Entorno Léxico*** es la implementación física que usa\nel motor de JavaScript para almacenar esas variables y mantener la referencia al ámbito padre.\n\nEn otras palabras, el ***Ámbito Léxico*** son las reglas del estándar ECMAScript que determinan cuál es el alcance o *scope* de las\nvariables, mientras que el ***Entorno Léxico*** es el lugar físico en memoria donde se almacena la estructura de datos de las\nvariables de una función, el ***Entorno Léxico*** se compone de dos elementos:\n- El ***Registro de Entorno***(o *Environment Record*): Es donde se almacenan las variables, constantes, funciones y parámetros\n  locales o declarados directamente dentro del scope de la función\n- Una referencia externa: La referencia o enlace al *entorno léxico* adyacente superior (*Outer Lexical Environment*).\n\nPrácticamente es el *entorno léxico* lo que permite que las closures puedan crearse y lo que explica cómo funciona a más bajo nivel\nel alcance de las variables y constantes.\n\nUn dato interesante y curioso es que algunas fuentes en internet mencionan que el entorno léxico de una función es almacenado en una\nvariable oculta llamada `[[Environment]]`.\n\n\n## Funciones que retornan funciones\n\nVeamos de nuevo nuestro primer ejemplo:\n\n``` js\nfunction padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n\t  \u002F\u002F hijo es la función interna que forma el closure\n    console.log(nombre) \u002F\u002F Podemos acceder a la variable nombre\n  }\n\n  hijo()\n}\n\npadre() \u002F\u002F Se muestra en la consola 'pemid'\n```\n\nEn este ejemplo, la variable `nombre` solo es usada dentro de la función `hijo` y solo se imprime en consola, una vez la función\n`padre` termina de ejecutarse, la variable `nombre` es marcada como lista para limpieza por el recolector de basura(*garbage collector*)\ny la liberación de su espacio en memoria, lo que hace que una vez terminada de ejecutarse ya no se pueda volver a acceder a la\nvariable `nombre` de ninguna manera.\n\nAhora bien, llegamos a la parte que se suele enseñar comúnmente cuando se explican las closures en JavaScript, las funciones que\nretornan funciones que tienen una referencia a una variable o constante declarada en la función padre, veamos este ejemplo:\n\n``` js\nfunction padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n    console.log(nombre)\n  }\n\n  return hijo\n}\n\nconst funcionHijo = padre() \u002F\u002F guardamos la referencia a la función hijo\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\n```\n\nPodemos acceder a la variable `nombre` incluso cuando la función donde fue declarada ya terminó su ejecución!!! 🤯\n\nPuede que esto te sorprenda, o puede que no porque es algo que ya has visto muchas veces y sabes que es el comportamiento que tienen\nlas closures, pero, ¿sabes realmente por qué podemos seguir accediendo a la variable `nombre` incluso después de que termina de\nejecutarse la función `padre`?\n\nAhora que hemos aprendido lo que es el *entorno léxico*, no es tan complicado entender esto, prácticamente podemos resumir lo que\nestá pasando con lo siguiente:\n\n1. Se declara la función `padre`, la cual en su cuerpo declara la variable `nombre`.\n2. Dentro de la función `padre` también se declara la función `hijo`, como vimos antes, en la función `hijo` se crea un\n   *entorno léxico*, en el cual hay una referencia hacia el *entorno léxico* superior(el de la función `padre`) y dentro de este\n   último está la variable `nombre` que está siendo usada dentro de la función `hijo`.\n3. La función `hijo` es retornada por la función `padre`.\n4. Se declara la constante `funcionHijo`(`const funcionHijo = padre()`), ahora en esta constante se guarda lo que retorna la función\n   `padre`, que es la referencia a la función `hijo` que fue declarada dentro de la función `padre`.\n5. Se termina de ejecutar la función `padre`, JavaScript intente hacer la limpieza o recolección de las variables declaradas en la\n   función `padre` porque ya terminó su ejecución, sin embargo, al ver la variable `nombre` se da cuenta que esta sigue siendo\n   referenciada dentro del *entorno léxico* de la función `hijo`, la cual sigue teniendo una referencia *\"viva\"*, la constante\n   `funcionHijo`, por lo que al no poderla destruir, la pasa a la memoria heap, donde vivirá hasta que ya no sea utilizada ni\n   referenciada en ningún lugar.\n6. Gracias a que esta referencia ahora se queda *\"viva\"*, al ejecutar `funcionHijo()` más adelante, podemos seguir viendo en la\n   consola `'pemid'`.\n\nCon esto ahora ya conoces más a fondo cómo es que funcionan las closures, ahora bien, solo para complementar esto, podríamos hacer\nuna limpieza manual de la referencia a la variable `nombre` de la siguiente manera:\n\n``` js\nfunction padre() {\n  let nombre = 'pemid'\n\n  function hijo() {\n    console.log(nombre)\n  }\n\n  return hijo\n}\n\n\u002F\u002F reemplazamos const por let para poder cambiar su valor más adelante\nlet funcionHijo = padre()\n\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\nfuncionHijo() \u002F\u002F 'pemid'\n\n\u002F\u002F Al cambiar ahora el valor guardado en la variable funcionHijo por undefined\n\u002F\u002F se pierde la referencia de la función hijo y su entorno léxico, por lo que\n\u002F\u002F ahora la variable nombre no se usa en ningún lugar por lo que puede ser\n\u002F\u002F destruida por el garbage collector\nfuncionHijo = undefined\n```\n\n\n## Usando Closures\n\nHagamos algunos ejemplos de uso de closures para entender mejor algunas formas de usar closures.\n\n### Creando fábricas de funciones\n\nVeamos esta función:\n\n``` js\nfunction crearTablaDeMultiplicar(factor) {\n  return function (multiplier) {\n    console.log(factor * multiplier)\n  }\n}\n```\n\nLa función `crearTablaDeMultiplicar` recibe el parámetro `factor`, el cual se usa en la función anónima que retorno, esta función\nque retorna también recibe un parámetro `multiplier`, como podemos ver en el código, se imprimirá en consola el producto resultante\nentre `factor` y `multiplier`, lo cual podemos usar de la siguiente manera:\n\n``` js\n\u002F\u002F Tabla del 5\nconst _5x = crearTablaDeMultiplicar(5)\n\n_5x(1) \u002F\u002F 5\n_5x(2) \u002F\u002F 10\n_5x(3) \u002F\u002F 15\n_5x(4) \u002F\u002F 20\n_5x(5) \u002F\u002F 25\n_5x(6) \u002F\u002F 30\n_5x(7) \u002F\u002F 35\n_5x(8) \u002F\u002F 40\n_5x(9) \u002F\u002F 45\n_5x(10) \u002F\u002F 50\n\n\u002F\u002F Tabla del 7\nconst _7x = crearTablaDeMultiplicar(7)\n\n_7x(1) \u002F\u002F 7\n_7x(2) \u002F\u002F 14\n_7x(3) \u002F\u002F 21\n_7x(4) \u002F\u002F 28\n_7x(5) \u002F\u002F 35\n_7x(6) \u002F\u002F 42\n_7x(7) \u002F\u002F 49\n_7x(8) \u002F\u002F 56\n_7x(9) \u002F\u002F 63\n_7x(10) \u002F\u002F 70\n```\n\nEn este ejemplo, la función `crearTablaDeMultiplicar` es una fábrica de funciones, ya que su ejecución crea nuevas funciones con\nalgunas *\"configuraciones predeterminadas\"* que serán compartidas las veces que se ejecute la función, en este caso, la\n*\"configuración predeterminada\"* es lo que se envía como argumento al parámetro `factor`.\n\nComo podemos ver, los *entornos léxicos* no se mezclan, si no que se crea uno cada vez que se guarda una nueva referencia de la\nfunción interna que forma el closure, y de esta forma manteniendo su independencia. De esta manera en la declaración\n`const _5x = crearTablaDeMultiplicar(5)`, en *entorno léxico* de la función interna guarda el valor de `5`, que fue el que se le\nmandó como argumento al parámetro `factor`, mientras que en la declaración `const _7x = crearTablaDeMultiplicar(7)`, el\n*entorno léxico* guarda el valor de `7`, pues ese fue el valor que se envió como argumento al parámetro `factor`.\n\n\n### Ejemplo de uso con HTML\n\nImaginemos que tenemos estos elementos HTML:\n\n``` html\n\u003Cbutton id=\"size-12\">12\u003C\u002Fbutton>\n\u003Cbutton id=\"size-14\">14\u003C\u002Fbutton>\n\u003Cbutton id=\"size-16\">16\u003C\u002Fbutton>\n```\n\nLa finalidad de estos botones es que al presionarlos cambien el tamaño de la fuente según corresponda, hay muchas formas en las que\npodríamos abordar este problema, sin embargo, en esta ocasión intentaremos resolverlo con closures, vemos el siguiente código:\n\n``` js\nfunction makeSizer(size) {\n  return function () {\n    document.body.style.fontSize = `${size}px`;\n  };\n}\n\nconst setSize12 = makeSizer(12);\nconst setSize14 = makeSizer(14);\nconst setSize16 = makeSizer(16);\n```\n\nEn la función `makeSizer`, como podemos ver, se forma un closure, puesto que en la función interna se hace referencia al parámetro\n`size` que nos llega en la función padre. Con esto podemos ver que la función `setSize12` guarda en su *entorno léxico* el valor\nde `12`, por lo que al ejecutar esta función el tamaño de fuente del *body* se cambiará a `12px`, lo mismo pasará con las funciones\n`setSize14` y `setSize16` con los valores `14px` y `16px` respectivamente.\n\nAhora podemos *\"bindear\"* estas funciones en los eventos `onclick` de los botones de la siguiente manera:\n\n``` js\ndocument.getElementById(\"size-12\").onclick = size12;\ndocument.getElementById(\"size-14\").onclick = size14;\ndocument.getElementById(\"size-16\").onclick = size16;\n```\n\nEn este ejemplo, las closures nos ayudaron a crear una fábrica de funciones y poder reutilizar nuestra lógica para distintos valores.\n\n\n### Propiedades privadas con ayuda de closures\n\nEn lenguajes cuyo paradigma es la programación orientada a objetos(POO), se pueden crear propiedades privadas, lo que significa que no\nse puede acceder a ellas más que dentro de la propia clase.\n\nAntes de ES6 no existían las clases en JavaScript, una forma que se usaba como *workaround* es emular estas propiedades privadas\ncreando closures, un ejemplo lo podemos ver a continuación, este ejemplo usa el *patrón de diseño de módulo*:\n\n``` js\nconst counter = (function () {\n  let privateCounter = 0\n\n  const changeBy = (value) => {\n    privateCounter += value\n  }\n\n  return {\n    increment() {\n      changeBy(1)\n    },\n    decrement() {\n      changeBy(-1)\n    },\n    getCounter() {\n      return privateCounter\n    }\n  }\n})()\n\nconsole.log(counter.getCounter()) \u002F\u002F 0\ncounter.increment()\ncounter.increment()\ncounter.increment()\nconsole.log(counter.getCounter()) \u002F\u002F 3\ncounter.decrement()\nconsole.log(counter.getCounter()) \u002F\u002F 2\nconsole.log(counter.privateCounter) \u002F\u002F undefined\n```\n\nComo podemos observar, en este ejemplo estamos usando una IIFE(*Immediately Invoked Function Expression*), lo que hace que en la\nconstante `counter` se guarde *\"en automático\"* lo que retorna esta función. Con este ejemplo podemos ver que realmente las closures\nno solo son *\"funciones que retornan otras funciones...\"*, sino que como vemos, estamos retornando un objeto con distintos métodos\nque a través de las closures mantienen viva la referencia a la variable `privateCounter` y a la constante `changeBy`, que a su vez\ninternamente crea también una closure con la variable `privateCounter` y como podemos observar en la última línea, no podemos acceder\ndirectamente a `privateCounter`, sólo a través de la función `getCounter`, así, emulamos comportamientos de la POO, como el\nencapsulamiento, con ayuda de las closures.\n\n\n### Closures sobre módulos\n\nLas closures también pueden generarse en distintos módulos, por ejemplo veamos lo siguiente:\n\n``` js [fooModule.js]\nlet foo = 5\nexport const getFoo = () => foo\nexport const setFoo = (value) => {\n  foo = value\n}\n```\n\nEste módulo crea un par de funciones *setter* y *getter* sobre la variable `foo`, lo que hace que aunque esta variable no sea\naccesible desde otros módulos, porque no está exportada, sí pueda ser alcanzada y modificada a través de las funciones `getFoo` y\n`setFoo`, que como podemos ver, han creado un closure con la variable `foo`:\n\n``` js [main.js]\nimport { getFoo, setFoo } from \".\u002FfooModule.js\"\n\nconsole.log(getFoo()) \u002F\u002F 5\nsetFoo(6)\nconsole.log(getFoo()) \u002F\u002F 6\n```\n\nLas closures también pueden ser creadas sobre valores importados y que se consideren *\"enlazados en vivo\"*, ya que al cambiar el\nvalor original cambia el valor importado en consecuencia, esto también es gracias a que los módulos en JavaScript se crean como un\n*singleton*, es decir, en todos los lugares donde se importe el módulo, realmente se estará usando la misma instancia del mismo,\nveamos el siguiente ejemplo para comprenderlo mejor:\n\n``` js [barModule.js]\nexport let bar = 1\nexport const setBar = (value) => {\n  bar = value\n}\n```\n\n``` js [closureCreator.js]\nimport { bar } from \".\u002FbarModule.js\"\n\n\u002F\u002F Se crea el closure sobre un enlace en vivo importado\nexport const getBar = () => bar \n```\n\n``` js [index.js]\nimport { getBar } from \".\u002FclosureCreator.js\"\nimport { setBar } from \".\u002FbarModule.js\"\n\nconsole.log(getBar()) \u002F\u002F 1\nsetBar(2);\nconsole.log(getBar()) \u002F\u002F 2\n```\n\nEn este ejemplo vemos que la variable `bar` se crea en `barModule.js`, y en este mismo módulo se exporta la función `setBar` para\npoder cambiar su valor; en el módulo `closureCreator.js` se crea el closure dentro de la función `getBar` y estas dos funciones\nexportadas por módulos distintos pueden ser usadas en un tercer módulo `index.js`, y al modificar la variable con la función `setBar`\ny volver a ejecutar la función `getBar`, podemos ver que el valor original de `bar` ha cambiado y la función `getBar` tiene acceso\nal nuevo valor actualizado.\n\n\n## Cadena de alcance de las closures\n\nGracias al *entorno léxico* que existe dentro de cada función cada vez que se crea una, los bloques anidados pueden acceder hasta\nlas variables que estén en *entornos léxicos* de niveles superiores, miremos el siguiente ejemplo:\n\n``` js\nconst globalValue = 10\n\nfunction padre() {\n  return function hija() {\n    console.log(globalValue)\n  }\n}\n\npadre()() \u002F\u002F 10\n```\n\nLo que pasa en este ejemplo es lo siguiente:\n\n- Se declara la constante `globalValue` en el *entorno léxico* global.\n- La función `padre` guarda en su *entorno léxico* dos cosas, el *registro de entorno*(que en este caso está vacío porque no hay\n  variables ni parámetros locales de la función `padre`) y la referencia al *entorno léxico* externo, que en este caso es el\n  *entorno léxico* global.\n- Dentro de la función `padre` se crea una nueva función, la función `hija`, esta función también tiene su propio *entorno léxico*,\n  que al igual que la función `padre`, tiene el *registro de entorno*, que también está vacío al no haber variables ni parámetros\n  en el ámbito local de la función `hija`, y la referencia al *entorno léxico* superior, que es el de la función `padre`.\n- Dentro de la función `hija` se intente leer la variable `globalValue`:\n  - JavaScript primero mira en el *registro de entorno* de la propia función `hija`, como no la encuentra, usa la referencia externa\n    guardada dentro de su *entorno léxico* para acceder al *entorno léxico* de la función `padre`.\n  - Busca la variable `globalValue` en el *registro de entorno* de la función `padre` pero tampoco la encuentra ahí, así que usa la\n    referencia externa que tiene el *entorno léxico* de la función `padre` para acceder al siguiente nivel, que en nuestro ejemplo\n    es el *entorno léxico global*.\n  - Al llegar al *entorno léxico global*, busca en el *registro de entorno* de este *entono léxico* la variable `globalValue`, en\n    este *registro de entorno* sí existe, por lo que accede a ela, lee su valor y opera con el mismo, en nuestro ejemplo simplemente\n    muestra el valor guardado en la consola.\n\nEs de esta manera como las funciones o bloques que están muy anidados pueden llegar a leer variables que se encuentren en\n*registros de entorno* de niveles superiores. Un modelo mental que podemos tener al momento de intentar entender este comportamiento\nes mirarlo como una lista simplemente enlazada(*single linked list*), cuyos valores se van enlazando desde el bloque más anidado\nhasta el de nivel superior.\n\nAlgo que me ayudó a comprender cómo estos valores se van enlazando es viéndolo de la siguiente manera, en nuestro ejemplo:\n\n``` js\nconst entornoLexicoDeFuncionHija = {\n  \u002F\u002F vacío porque no hay variables ni parámetros declarados en la función hija\n  registroDeEntorno: {},\n\n  \u002F\u002F referencia al entorno léxico de la función padre\n  referenciaExterna: {\n    \u002F\u002F vacío porque no hay variables ni parámetros declarados en la función padre\n    registroDeEntorno: {},\n\n    \u002F\u002F referencia al entorno léxico global\n    referenciaExterna: {\n      \u002F\u002F en este entorno léxico si está declarada la variable globalValue\n      registroDeEntorno: {\n        globalValue: 10\n      },\n\n      referenciaExterna: null \u002F\u002F ya no hay porque este es el entorno léxico global\n    }\n  }\n}\n```\n\nAunque esto es un resumen muy abstracto de cómo se van enlazando los *entornos léxicos*, puede ayudarnos a comprender cómo es que\ndesde funciones o bloques muy anidados JavaScript puede acceder a variables de entornos superiores.\n\nDe manera general y resumida podemos decir que cada bloque tiene 3 alcances:\n\n- El alcance local (Registro de Entorno)\n- El alcance adyacente o envolvente (a través de las referencias externas del *entorno léxico*)\n- El alcance global (gracias a los enlaces que existen en los *entornos léxicos* adyacentes)\n\nEsto mismo es lo que pasa cuando tenemos muchas closures anidadas de la siguiente manera:\n\n``` js\nconst e = 10\n\nfunction sum(a) {\n  return function sum1(b) {\n    return function sum2(c) {\n      return function sum3(d) {\n        return a + b + c + d + e\n      }\n    }\n  } \n}\n\nconsole.log(suma(1)(2)(3)(4)) \u002F\u002F 20\n```\n\nGracias a los *entornos léxicos* enlazados es que la función `sum3` puede acceder y leer todos los valores de `a`, `b`, `c`, `d` y `e`,\na esto es a lo que se conoce como ***cadena de alcance de las closures***, lo cual ahora ya sabemos por qué funciona.\n\nComo dato adicional, la expresión que escribimos en el ejemplo anterior `suma(1)(2)(3)(4)` está usando una técnica que se llama\n***Currying***, la cual, en JavaScript, también depende de las closures para poder funcionar.\n\n## Recomendaciones y buenas prácticas al usar closures\n\nAunque las closures son una característica poderosa y nos pueden ayudar a resolver varios problemas, es necesario tener en cuenta\nalgunas recomendaciones y buenas prácticas al usarlas, recuerda, un gran poder conlleva una gran responsabilidad.\n\n- **Privatizar datos y variables**: Usa closures para ocultar variables del alcance global. Esto evita que otros scripts modifiquen\n  tus datos accidentalmente. Define variables dentro de una función y expón solo los métodos para interactuar con ellas.\n- **Evitar fugas de memoria(Memory Leaks)**: Los closures mantienen vivas las variables de su entorno externo, lo que puede impedir\n  que el recolector de basura libere esa memoria. Limpia las referencias asignando `null` o `undefined` a las variables o funciones\n  que ya no vayas a utilizar.\n- **Crear fábricas de funciones(Factory Functions)**: Aprovecha los closures para generar funciones personalizadas basadas en\n  argumentos iniciales. Esto promueve la reutilización de código. Pasa un parámetro a la función principal para configurar el entorno\n  y retorna una nueva función adaptada.\n- **Mantener la legibilidad y evitar el abuso**: Anidar demasiados closures puede hacer que el código sea difícil de leer, depurar\n  y mantener. Usa closures cuando aporten un beneficio claro(como el encapsulamiento), no por defecto en cada función.\n\n\n## Cierre\n\nAhora ya conoces realmente lo que son las closures y cómo funciona a más bajo nivel esta característica del lenguaje JavaScript, sin\nembargo, no significa que ahora tengas que usar closures en todas partes, siempre ten en mente que cada nuevo concepto que aprendemos\nes una herramienta nueva que agregamos a nuestro arsenal, de esta manera, cuando estemos resolviendo un problema sepamos que esa\nherramienta existe y podemos hacer uso de ella para llegar a algunas soluciones si es necesario, aunque también siempre recuerda que\nes nuestra labor y responsabilidad como ingenieros de software saber cuando sí usar una herramienta y cuando no, así como las\nventajas y desventajas frente a otras posibles soluciones con otras herramientas distintas.\n\nEspero que este artículo te haya gustado y hayas aprendido algo nuevo, sin más me despido, nos vemos en la próxima entrega.\n",{"title":5,"description":3745},"blog\u002Fclosures-a-fondo-en-javascript","lXgrvSNIJWV_breBob9xzAZSdX195HepOYyhIhhjdyE",[3756,3757],null,{"title":3758,"path":3759,"stem":3760,"description":3761,"children":-1},"Unknown y Never en TypeScript","\u002Fblog\u002Funknown-y-never-en-typescript","blog\u002Funknown-y-never-en-typescript","Una introducción a los tipos unknown y never, sus principales características y posibles usos.",1789188660745]