¿Qué es exactamente un “cierre” en JavaScript?

Las funciones en JavaScript usan lo que se llama el ‘entorno léxico’, lo que significa que tiene acceso a variables definidas en el exterior, pero a las definidas en el interior solo se puede acceder desde dentro.

  función externa () {
   let x = 'Diseñador web';
   función shout () {
   alerta (`Me encanta $ {x}!`);
   }
   gritar();  }

Llamar a external () mostrará ‘I love Web Designer!’, Pero si se hace referencia a ‘shout’ o ‘x’ fuera de outside () , ambos estarán indefinidos. Un cierre es una combinación de una función junto con su entorno léxico. En este caso, el cierre es la función ‘externa’.

Estos son útiles al crear múltiples componentes, ya que cualquier cosa declarada dentro no afectará a otros. Se pueden usar para crear funciones y variables privadas de manera similar a otros lenguajes orientados a objetos como Python. El patrón de módulo utiliza cierres ampliamente para proporcionar formas estructuradas para que los módulos interactúen.

Para más publicaciones, consulte el blog de la compañía Solar Digital.

Si te gusta el comentario, ¡vota!

¡Hola!

Te voy a contar un secreto. Los cierres son un concepto difícil. Las personas arrojan palabras como alcance y persistencia, pero no explican realmente a qué se refieren. Al menos en una medida que la persona promedio puede comprender rápidamente.

Esto es tan frecuente que escribí un artículo al respecto: Destruyendo edificios: una guía simple para los cierres de JavaScript, pero ahora te daré la versión condensada.

Lo primero que debe comprender es que las funciones pueden devolver cualquier cosa .

  function my_function () {
 retorno 1;
 }

La función anterior devuelve un número. Ese número es 1.

  function my_function () {
 devolver "hola";
 }

La función anterior devuelve una cadena. Esa cadena es “hola”.

Y así sucesivamente y así sucesivamente. Puede devolver una matriz . Puede devolver un booleano.

La forma de recuperar esos valores de retorno es invocar ( o llamar ) la función declarada. Me gusta esto:

  function my_function () {
 devolver "hola";
 }

 var demo_variable = my_function ();  // invocar la función usando parens

 console.log (demo_variable);  // "Hola"

Para desglosar lo anterior:

  1. Las funciones pueden devolver cualquier cosa
  2. Para recuperar el valor de retorno de una función, podemos invocarlo y almacenar el valor devuelto en una variable.

Lo siguiente que debe comprender es que cuando digo ” Una función puede devolver cualquier cosa “, esto incluye funciones.

Eso puede ser difícil de entender, así que echemos un vistazo al código para explicar:

  function my_function () {
   función de retorno () {

   };
 }

Actualmente esta función devolverá una función vacía. Esto es solo para mostrar la estructura metálica de lo que sucede debajo del capó.

Al igual que las reglas del club de lucha, la primera regla es “Una función puede devolver cualquier cosa ”, y la segunda regla es “Una función puede devolver cualquier cosa ”. ¿Qué quiero decir con eso? Actualmente tenemos una función que devuelve una función:

  function my_function () {
   función de retorno () {

   };
 }

También podemos tener una función que devuelva una función … que devuelva cualquier otra cosa .

  function my_function () {
   función de retorno () {
     retorno 1;
   };
 }

En lo anterior, tenemos una función que devuelve una función, que devuelve un número.

¿Cómo recuperamos la función interna y su número devuelto?

  function my_function () {
   función de retorno () {
     retorno 1;
   };
 }

 var demo_variable = my_function ();  // devuelve la función interna.
 // la función interna ahora está almacenada en demo_variable

 var demo_variable_2 = demo_variable ();  // devuelve el 1

 console.log (demo_variable_2);  // 1

Esto puede ser un poco complejo de ver, pero todo lo que está sucediendo es esto:

  1. declaramos una función, my_function, que devuelve una función, que devuelve un 1.
  2. Invocamos my_function, y su valor de retorno se almacena en demo_variable
  3. demo_variable ahora es una función que devuelve un 1
  4. Invocamos la función demo_variable, que devuelve un 1, y la almacenamos en demo_variable_2
  5. registramos demo_variable_2

Si todavía tiene problemas hasta ahora, lea lo anterior nuevamente. Cópielo en jsfiddle o codepen y juegue con él. Es importante que entiendas esto hasta ahora.

Si comprende todo hasta este punto, felicidades, está a punto de aprender cierres.

En cuanto a envolver la cabeza con los cierres, esta es la parte difícil. Vamos a comenzar lentamente de nuevo con una función estándar. ¡Solo que esta vez, vamos a devolver una variable!

  function my_function () {
 var my_number = 0;
 devuelve my_number;
 }

Puedes imaginar que esto no cambia nada. Devolvemos la variable my_number, y si tuviéramos que recuperar el valor de la función de esta manera:

  var demo_variable = my_function ();
 console.log (demo_variable);  // 0

Invariablemente ( ¡ja! ) Obtenemos el valor 0.

Si no sabe, el símbolo ++ simplemente agregará 1 a una variable. No estoy tratando de engañarte aquí, pero trato de responder esta pregunta. ¿Cuál será demo_variable si ejecutamos esta función?

  function my_function () {
 var my_number = 0;
 devuelve my_number ++;
 }
 var demo_variable = my_function ();

Si lo piensa, todo lo que estamos haciendo es establecer la variable my_number en 0, y luego agregarle 1.

Aquí es donde entramos en la persistencia. Puede sonar complicado, pero no lo pienses demasiado. Todo lo que la palabra significa en este contexto es que si invocamos esta función una y otra vez, el valor de retorno no persistiría porque cada invocación de función es su propia instancia. Básicamente vive en su propio pequeño mundo con su propia variable my_number . En código quiero decir esto:

  var demo_variable = my_function (); 

 // lo anterior no tiene correlación con lo siguiente.
 // son instancias separadas, mundos separados
 // my_number está disponible en ambas funciones
 // pero no son lo mismo my_number

 var demo_variable_2 = my_function ();

Entonces, ¿cómo podríamos lograr que la variable my_number persista ? Bueno, primero debe comprender esta regla sobre las funciones:

“Todas las funciones se eliminan de la memoria cuando ya no son necesarias o están en uso”.

Esto significa que todas las variables de función (my_number) dejan de existir una vez que la función ha terminado de ejecutarse. Esto significa que tan pronto como el navegador esté seguro de que esta función se haya ejecutado, se eliminará de la memoria.

¿No sería bueno si pudiéramos inyectar un marcador de posición en la función para que el navegador nunca estuviera seguro de que terminó de ejecutarse? Algo como, no sé, ¿una referencia a una función interna?

  function my_function () {
 var my_number = 0;
   función de retorno () {
     devuelve my_number ++;
   }
 }

Lo anterior puede parecer confuso, pero trate de no pensar demasiado. La forma en que esto funciona es la siguiente:

  1. crear función, my_function, que declara una variable my_number y le da un valor.
  2. devuelve una función de my_function, que establece my_number en sí mismo + 1, y devuelve my_number.

En la práctica, esto se ve así:

  function my_function () {
 var my_number = 0;
   función de retorno () {
     devuelve my_number ++;
   }
 }

 var demo_variable = my_function ();  // declara my_number = 0, función de retorno
 console.log (demo_variable ()); // invocar demo_variable, devolver my_number ++ (0 + 0)
 demo_variable (); // invocar demo_variable, devolver my_number ++ (0 + 1)
 demo_variable (); // invocar demo_variable, devolver my_number ++ (1 + 1)
 console.log (demo_variable ());  // 3 (devuelve my_number (2 + 1)) le (); // invoca demo_variable, devuelve my_number ++ (2 + 1)
 console.log (demo_variable ());  // 4 (devuelve my_number (3 + 1))

Puedes jugar con la demo aquí: Editar violín – JSFiddle

Lo que sucede es que, debido a que demo_variable siempre hace referencia al código dentro de my_function, my_function no se puede eliminar de la memoria. Como my_function no se puede eliminar de la memoria, my_number persiste.

Así es como funcionan los cierres.

Si esta respuesta no lo hace por usted y está buscando una lección mucho más profunda, eche un vistazo al artículo Destrucción de edificios: una guía simple para los cierres de JavaScript: se ha recibido bien y posiblemente pueda eliminar cualquier Más preguntas que pueda tener.

¡Feliz codificación!

Hay cientos de tutoriales que explican (o al menos intentan explicar) qué son los cierres de Javascript, y aunque la mayoría de ellos obtienen la mayor parte de la parte correcta, en mi experiencia, leen un artículo y cuando alguna parte no está clara, intentan complementar de otro artículo hace un desastre total en el cerebro. ¿Correcto? 🙂
Los cierres son, de hecho, una de las cosas más típicas y confusas sobre JS de esa manera.

Desde lo más básico, piénselo de esta manera: Los cierres son, de hecho, el resultado de que todas las cosas JS son en realidad objetos de la naturaleza, y el hecho de que “un cierre se forma cuando devuelve una función interna de una función externa” es cierto porque seamos sinceros, todas las funciones JS son en realidad objetos . Y los objetos tienen ciertas idiosincrasias 😛

Aquí hay un excelente tutorial sobre el quid de los cierres que, en mi opinión, es uno de los mejores disponibles en Internet. Sígalo, la explicación y los ejemplos son simples y maravillosos.

Comprenda los cierres de JavaScript con facilidad

Dicho esto, aquí hay un par de otras cosas sobre los cierres que he aprendido en mi experiencia y creo que serían útiles para que los entiendas mejor:

  • Los cierres no son realmente de otro mundo y una función en realidad no tiene que devolver una función interna para formar un cierre. Una función que simplemente accede a una variable fuera de su alcance inmediato también es técnicamente un cierre …
  • La primera impresión de comprensión de los cierres se rompe cuando los mezcla con bucles . Si no está seguro de comprender bien los cierres, intente implementarlos en un bucle. Despeja muchos conceptos erróneos. Piense en objetos JS y referencias .

Y recuerde, para comprender efectivamente los cierres, debe tener una muy buena comprensión de qué contexto y elevación en JS son. De lo contrario, pronto volverá a ser un desastre otra vez 🙂

Además, vaya a esta publicación de desbordamiento de pila. ¡Es genial!

¿Cómo funcionan los cierres de JavaScript?

Espero que esto ayude 🙂