Saltar a un capítulo clave
Comprender los cierres de Javascript
Al sumergirse en el mundo de Javascript, es imposible pasar por alto la importancia de los cierres. La capacidad de una función para recordar y acceder a su ámbito incluso cuando se está ejecutando fuera de su ámbito léxico es esencialmente lo que caracteriza a los Cierres Javascript.
Definir qué es una función de cierre en Javascript
Profundizando en los Cierres de Javascript, empecemos por definir qué son.
Un Cierre en Javascript es una función que tiene acceso a su propio ámbito, al ámbito de la función externa y al ámbito global.
- Su propio ámbito - variables definidas entre sus llaves { }
- El ámbito de la función externa - variables definidas en la función externa
- El ámbito global - variables definidas como variables globales
Además, un cierre te permite acceder al ámbito de una función externa desde una función interna. En JavaScript, los cierres se crean cada vez que se crea una función, en el momento de creación de la función.
Ámbito propio | Variables definidas dentro del cierre |
Ámbito de la función externa | Variables de la función en la que se encuentra el cierre |
Ámbito global | Variables globales |
Veamos un ejemplo:
function outerFunction() { let outerVariable = 'Soy de la función externa'; function innerFunction() { console.log(outerVariable); } return innerFunction; } let closureFunction = outerFunction(); closureFunction();
Cuando llamamos a la función closureFunction, ésta puede seguir accediendo a la variable outerVariable desde su ámbito externo, incluso después de que la función haya retornado.
Análisis de los conceptos básicos de la función de cierre en JavaScript
Los cierres son uno de los conceptos clave de Javascript y también una de sus características más potentes. En realidad, son una consecuencia del ámbito léxico. Para entenderlas bien, primero tienes que conocer el ámbito léxico y las funciones de primera clase.
El término léxico se refiere a la fase de compilación de tu código, y es donde cosas como la declaración de variables se organizan en una jerarquía de ámbitos.
El ámbito léxico es la capacidad de un ámbito de función para acceder a las variables de un ámbito externo (contenedor).
¿Y qué pasa con las funciones de primera clase? En Javascript, las funciones pueden asignarse a variables, almacenarse en un objeto o pasarse como argumentos de función. Esto es a lo que nos referimos como que el lenguaje trata a las funciones como ciudadanos de primera clase.
Considera esto: los cierres son un vínculo con el ámbito de la función externa durante todo el ciclo de vida de la función que se ejecuta e incluso después de la finalización de la ejecución de la función. El poder de los cierres se hace especialmente evidente al crear privacidad de datos y fábricas de funciones.
Veamos otro ejemplo:
function outerFunction(outerVariable) { return function innerFunction(innerVariable) { console.log('Variable externa: ' + outerVariable); console.log('Variable interna: ' + innerVariable); } } let closureFunction = outerFunction('hola'); closureFunction('mundo'); //logs: Variable externa: hola, Variable interna: mundo
En este ejemplo, la función externa ha regresado, pero el ámbito que crea la función interna mantiene la variable externa. Y eso es esencialmente un cierre: agrupa la función junto con su estado circundante, o entorno léxico, formando un cierre.
Profundizar en el ejemplo de cierre de JavaScript
Explicar conceptos teóricos es una cosa, pero entender los Cierres de Javascript realmente brilla con ejemplos. Descubrirás que son una herramienta poderosa una vez que empieces a trabajar con ellos en el código del mundo real.
Análisis práctico de un ejemplo sencillo de cierre JavaScript
Vamos a desglosar un ejemplo sencillo de un Cierre JavaScript para darte un enfoque práctico de la comprensión de este concepto. A menudo, cuando los vemos en acción es cuando realmente brilla el poder de los cierres.
function makeAdder(x) { return function(y) { return x + y; }; } let add5 = makeAdder(5); let add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12
En este ejemplo, makeAdder es una fábrica de funciones: crea funciones que pueden añadir un valor específico a su argumento. En el caso anterior, la fábrica de funciones crea dos nuevas funciones: una que añade 5 a su argumento y otra que añade 10.
add5 y add10 son cierres. Comparten la misma definición del cuerpo de la función, pero almacenan entornos léxicos distintos. En el entorno léxico de add5, x es 5, mientras que en el caso de add10, x es 10.
Es valioso comprender cómo trata el motor de JavaScript el código anterior:
- El motor de JavaScript define primero la función makeAdder y la eleva a la parte superior.
- A continuación, se desplaza línea por línea y ve la inicialización de las funciones add5 y add10.
- Cada vez que ejecute makeAdder, producirá un cierre y lo asignará a add5 y add10.
- Finalmente, se ejecuta el código dentro de la función.
Así es como se aplica la teoría de forma práctica en los cierres de JavaScript. El ejemplo anterior es bastante sencillo de entender, pero potente en el sentido de que introduce el patrón de fábrica, muy utilizado en JavaScript.
Los cierres permiten a los programadores de JavaScript escribir un código mejor, más sucinto y más expresivo. Tienen propiedades necesarias para la programación funcional y sus capacidades de ocultación y encapsulación de datos pueden utilizarse también para imitar conceptos de programación orientada a objetos.
Uso avanzado: Profundizar en JavaScript Ejemplo de cierre
Siguiendo adelante, vamos a discutir un caso de uso más avanzado de los Cierres JavaScript. Más concretamente, cómo pueden mantener el estado en ausencia de clases y objetos. Este aspecto es especialmente útil para crear privacidad de datos y fábricas de funciones.
let contador = (function() { let contadorPrivado = 0; function cambioPor(val) { contadorPrivado += val; } return { incremento: function() { cambioPor(1); }, decremento: function() { cambioPor(-1); }, valor: function() { retorno contadorPrivado; }; })(); console.log(contador.valor()); // 0 contador.incremento(); contador.incremento(); console.log(contador.valor()); // 2 contador.decremento(); console.log(contador.valor()); // 1
En este ejemplo de cierre avanzado de JavaScript, el contador es un objeto con métodos incrementar, decrementar y valor.
El entorno léxico de estas funciones contiene dos elementos:
- la variable privateCounter, a la que no se puede acceder directamente desde fuera de la función anónima y
- la función changeBy.
Ambos elementos sólo existen dentro de la función anónima. Forman un ámbito privado, o un cierre. Debido a su ámbito, mantienen su estado entre las llamadas a la función. Este patrón se utiliza mucho en JavaScript para crear objetos con datos y métodos privados, a los que no se puede acceder desde el exterior.
Así, al ejecutar la función incrementar se añade el valor 1 a privateCounter. Ejecutar la función valor devolverá la cantidad actual almacenada en privateCounter. Como esta variable no es accesible directamente fuera de la función anónima, el cierre actúa como un objeto con datos privados.
Si dominas estos ejemplos avanzados, no sólo escribirás JavaScript, ¡lo hablarás con fluidez!
Explorando el caso de uso del cierre en JavaScript
Al examinar los Cierres de JavaScript en acción es cuando se pone de manifiesto su verdadera destreza. Los casos de uso de los Cierres JavaScript son abundantes y prácticos en la programación cotidiana, desde fábricas de funciones hasta privacidad y encapsulación de datos.
Descubrir los casos de uso de los Cierres JavaScript en la programación cotidiana
Hay algo increíblemente fascinante en los Cierres JavaScript: son casi como agentes secretos que guardan cierta información privada a la que sólo puede acceder una función interna especial. Explorar el caso de uso de los Cierres JavaScript, como emular métodos privados, crear fábricas de funciones y retrasar la ejecución de funciones, muestra el poder de esta versátil función.
- Emular métodos privados: En muchos lenguajes de programación orientados a objetos, es habitual utilizar variables y métodos privados a los que no se puede acceder directamente desde fuera del objeto. Aunque JavaScript, un lenguaje basado en objetos, no admite de forma natural miembros privados, podemos utilizar cierres para emular métodos privados y crear una zona de ámbito privado.
- Crear fábricas de funciones: Las fábricas de funciones son funciones que devuelven otras funciones, lo que nos permite crear plantillas de funciones que se pueden personalizar cuando las invocamos. Utilizando funciones que devuelven otras funciones con comportamientos específicos en función de los argumentos que les pasemos, podemos crear funciones únicas y personalizadas con facilidad.
- Retrasar la ejecución de una función: Puedes retrasar la ejecución de una función, por ejemplo, en setTimeOut, escuchadores de eventos o llamadas AJAX utilizando cierres.
Un ejemplo claro de un cierre JavaScript en funcionamiento es en los controladores de eventos. Considera el siguiente ejemplo:
const botones = document.getElementsByTagName('botón'); for (let i=0; i
En este ejemplo de cierre JavaScript, al hacer clic en el botón correspondiente se registra el número de botón correcto porque el cierre del manejador de eventos de clic tiene acceso a la variable i desde el ámbito externo cuando se adjuntó el manejador de eventos. El valor de i se conserva y recuerda incluso cuando se hace clic más tarde.
Cómo aprovechar el cierre de JavaScript en situaciones reales
Liberar el poder de los cierres de JavaScript en escenarios del mundo real aumenta la eficiencia y aporta más solidez a tu desarrollo. Los casos de uso modulares, flexibles y concisos de los Cierres JavaScript pueden hacer que parezcan complejos, pero si se comprenden, se convierten en armas sustanciales en el arsenal de un desarrollador.
Mantener el estado: En las aplicaciones JavaScript, el estado suele mantenerse en objetos y matrices. Los cierres de JavaScript te permiten almacenar un estado, privado y a salvo de manipulaciones, que persiste incluso después de que la función externa haya sido devuelta. Estos cierres pueden acceder a los datos y manipularlos en su ámbito léxico, es decir, el ámbito en el que fueron declarados. Devolver sincrónicamente y referenciar continuamente esta función autocontenida, junto con su estado privado oculto, permite la encapsulación y la modularidad de tu código.
Encapsulación de datos y privacidad: Los cierres de JavaScript te permiten crear datos privados. Todo lo que no devuelva la función interna seguirá siendo privado, lo que proporciona una forma de encapsular o envolver datos y métodos, que puede evitar la contaminación del espacio de nombres global y las modificaciones accidentales. Podemos exponer sólo lo necesario y mantener el resto de la información oculta al ámbito global. Esto también reduce la probabilidad de conflictos de nombres de variables.
Evitar el problema de los bucles for: Los bucles for con var en JavaScript suelen crear confusión y errores. Cuando se utiliza var en un bucle y las variables del bucle tienen algunas devoluciones de llamada asíncronas, a menudo no se comporta como cabría esperar. Para obtener el comportamiento adecuado, necesitas crear un nuevo ámbito, lo que puede conseguirse utilizando cierres de JavaScript.
Aquí tienes un ejemplo relevante de cierre JavaScript:
for (var i = 1; i <= 3; i++) { (function(i) { setTimeout(function() { console.log(i) }, 1000); })(i); }
En el comportamiento anterior, hemos invocado inmediatamente una función creando un nuevo ámbito. En este ámbito, i tiene su propio valor, que no cambiará, por lo que el valor de i es el que esperamos cuando se ejecute la función.
Si aprendes a aprovechar los cierres de JavaScript en situaciones reales, los desarrolladores podrán utilizar todo el potencial de esta potente función y escribir un código más limpio, eficiente y robusto.
Aplicaciones de los cierres de JavaScript
Los cierres de JavaScript son un aspecto fundamental del lenguaje y tienen muchas aplicaciones en diversos ámbitos de la Informática. Desde la gestión del estado en aplicaciones JavaScript hasta la generación de variables y métodos privados, los Cierres ofrecen una potente funcionalidad y ayudan a escribir código robusto y eficiente.
Diversas aplicaciones de los Cierres de JavaScript en Informática
Tanto si estás construyendo un simple sitio web dinámico como trabajando en una aplicación web avanzada, la versatilidad de los Cierres JavaScript es omnipresente en el ámbito de la Informática. Sus aplicaciones son amplias y diversas, y van desde la gestión de estados y el control del ámbito de las variables hasta la emulación de métodos privados y el encapsulamiento de datos dentro de su ámbito.
Una aplicación común de los Cierres de JavaScript es su uso en manejadores de eventos y retrollamadas. Cuando se produce un evento (como hacer clic en un botón), se ejecuta la función. Sin embargo, esto no se realiza en el ámbito global, sino dentro del cierre, que tiene acceso a las variables de su función padre, así como a cualquier variable global.
Los cierres brillan en situaciones en las que necesitas hacer un seguimiento de la información a lo largo del tiempo y a través de múltiples llamadas a funciones. Es una forma de "recordar" y seguir teniendo acceso a las variables que estaban en el ámbito en el momento en que se creó el cierre. Las funciones que "gestionan" o "siguen la pista" de conjuntos de operaciones relacionadas son casos de uso perfectos para los cierres.
Su otra aplicación puede verse en el currying de funciones, una técnica para transformar una función con múltiples argumentos en una serie de funciones que toman cada una un único argumento. He aquí un ejemplo:
function multiplicar(a) { return function ejecutarMultiplicar(b) { return a * b; }; } const doble = multiplicar(2); console.log(doble(3)); // 6 console.log(doble(4)); // 8
En el ejemplo anterior, la función multiplicar crea un cierre, que contiene una referencia: la función ejecutarMultiplicar. Ésta se guarda en una variable double y se puede utilizar más adelante en el script. Esto también se conoce como currying de funciones.
Los cierres también te dan más control cuando trabajas con JavaScript asíncrono y cuando quieres mantener la manipulación de variables cerca de donde se utiliza la variable.
El amplio alcance y utilización de los cierres de JavaScript en la programación avanzada
Los Cierres JavaScript se utilizan ampliamente en escenarios de programación avanzada, especialmente cuando se trata de gestionar la complejidad y escribir código limpio, mantenible y eficiente.
En el diseño modular y la programación modular, los cierres pueden desempeñar un papel fundamental para separar las preocupaciones y encapsular la funcionalidad del programa en módulos reutilizables. Aquí puedes crear objetos con métodos públicos que tengan acceso a variables privadas (y a otros métodos privados) mediante cierres.
Considera el siguiente ejemplo:
let bankAccountModule = (function() { let privateBalance = 0; function privateDeposit(amount) { privateBalance += amount; } return { publicDeposit: function(amount) { privateDeposit(amount); }, publicCheckBalance: function() { return privateBalance; } } })(); bankAccountModule.publicDeposit(500); console.log(bankAccountModule.publicCheckBalance()); // 500
En el ejemplo anterior, el objeto bankAccountModule no puede acceder directamente a las funciones privateBalance o privateDeposit. En su lugar, éstas se mantienen privadas y protegidas de cualquier modificación externa. La única forma de interactuar con ellas es a través de los métodos públicos proporcionados.
En Programación Funcional, los cierres de JavaScript permiten un control más preciso del ámbito y ofrecen la posibilidad de conservar una referencia duradera a las variables, lo que facilita la escritura de funciones puras y evita los efectos secundarios. También te dan la posibilidad de escribir funciones de orden superior, que son funciones que operan sobre otras funciones, ya sea tomándolas como argumentos o devolviéndolas, lo que proporciona un código más dinámico y flexible.
Los cierres también son fundamentales para el uso correcto de las funciones de devolución de llamada, muy utilizadas en JavaScript para la programación asíncrona. Permiten que las retrollamadas tengan acceso a las variables de su función contenedora, manteniendo la resolución de variables independiente de cuándo y dónde se llame y ejecute la función.
En resumen, el amplio alcance y utilización de los Cierres de JavaScript en la programación avanzada proporciona una serie de potentes herramientas para escribir código limpio, eficiente y mantenible en una amplia variedad de escenarios.
Dominar los cierres de JavaScript
En el ámbito de la programación en JavaScript, uno de los temas más avanzados con los que puedes lidiar es el concepto de cierres. En pocas palabras, los cierres de JavaScript son funciones que tienen acceso al ámbito principal, incluso después de que la función principal se haya cerrado. Comprender este concepto es un salto crucial hacia el dominio de JavaScript, sobre todo para entender y utilizar marcos de trabajo y bibliotecas complejas.
Ventajas y retos del uso de los cierres de JavaScript
Profundizando en los Cierres JavaScript, es evidente que ocupan un nicho esencial en el panorama de la programación, gracias a una serie de ventajas notables. Sin embargo, dominar esta herramienta también exige superar ciertos retos.
En el lado de las ventajas, los principales beneficios son la Privacidad de los Datos, la Eficiencia de la Memoria y la Modularidad y Reutilización del Código.
- Privacidad de datos: JavaScript no admite propiedades o métodos privados dentro de un objeto. Sin embargo, los cierres ayudan a los desarrolladores a imitar este comportamiento. Los datos encerrados sólo están disponibles para la función que los encierra y para cualquier otra función que se declare dentro del mismo ámbito, manteniendo la integridad y la confidencialidad.
- Eficiencia de memoria: Los cierres de JavaScript tienen una forma de "recordar" su ámbito léxico, que incluye las variables disponibles para la función en el momento de su definición. Este uso eficiente de la memoria es especialmente beneficioso, por ejemplo, cuando se crea un gran número de instancias de un objeto.
- Modularidad y reutilización del código: Gracias a su capacidad para encapsular la funcionalidad y mantener el estado privado, los cierres se prestan naturalmente a producir un código más modular y reutilizable. Por ejemplo, permiten crear funciones de fábrica o funciones que devuelven otras funciones, estableciendo una nueva capa de abstracción y reutilización.
Además, los cierres son parte integrante de la programación funcional en JavaScript, ya que permiten que las funciones tengan "memoria". También desempeñan un papel importante en patrones de codificación específicos de JavaScript, como el Patrón de Módulo y Currying.
A pesar de sus inestimables aplicaciones, el uso de los cierres de JavaScript no está exento de dificultades. A menudo surgen dificultades para comprender su complejo comportamiento. He aquí algunos de los retos más comunes:
- Comprender el ámbito y el contexto de ejecución: Dado que los cierres implican que una función interna tiene acceso a las variables de la función externa (que los encierra), es necesario conocer a fondo el ámbito de las variables y cómo funcionan los contextos de ejecución en JavaScript. Esto incluye conocimientos sobre el entorno de las variables (ámbito local, ámbito global), el entorno léxico y la pila de ejecución.
- Consumo de memoria: Aunque los cierres son eficientes desde el punto de vista de la memoria en determinadas circunstancias, podrían dar lugar a un uso excesivo de memoria si no se manejan adecuadamente. Dado que un cierre retiene todas las variables de su ámbito, podría dar lugar a un uso de memoria superior al necesario, haciendo que el código se ejecute más lentamente, sobre todo si el cierre se adjunta a una variable u objeto global y no se desreferencia después de su uso.
- Complejidad en la Programación Asíncrona: Los cierres también se utilizan mucho en JavaScript asíncrono, donde su comprensión es crucial, ya que la función de devolución de llamada puede acceder a su ámbito padre, manteniendo vivas las variables más tiempo del que cabría esperar en un contexto síncrono. La dificultad radica en la gestión del tiempo, la secuencia y la sincronización de los eventos.
Es cierto que algunos de estos retos se derivan de aspectos fundamentales del propio JavaScript, como el comportamiento asíncrono y el ámbito de las variables. Sin embargo, una sólida comprensión de estos conceptos puede ayudar a superar los retos relacionados con los cierres de JavaScript.
Mejora tus habilidades de programación con los cierres de JavaScript
Elevar tus habilidades de programación con un conocimiento exhaustivo de los cierres de JavaScript puede realmente diferenciarte de la multitud. Junto con una mayor comprensión de principios fundamentales como la privacidad de los datos y el ámbito de las variables, el conocimiento de los cierres de JavaScript puede capacitarte para manejar escenarios de programación más avanzados con confianza.
Los cierres se utilizan ampliamente en bibliotecas y marcos de trabajo de JavaScript, como React y Angular, donde es absolutamente necesario comprender los conceptos de cierre. Considera un controlador de eventos en React:
function App() { const [count, setCount] = useState(0); const increment = () => { setCount(currentCount => currentCount + 1); }; return ( ); }
En el ejemplo React anterior, useState devuelve una variable de estado (count) y una función para actualizarla (setCount). La función pasada a setCount utiliza un cierre para acceder al valor actual de count cuando se ejecuta la función de incremento. Esto demuestra cómo el dominio de los cierres te ayuda a utilizar y comprender plenamente las bibliotecas y marcos de trabajo populares de JavaScript.
Además, los cierres de JavaScript pueden transformar tu enfoque de la depuración y la resolución de problemas, ya que comprenderás mejor los ámbitos de las variables y la pila del contexto de ejecución. Podrás predecir mejor el comportamiento de tu código, desentrañar la causa de los fallos con mayor eficacia y elaborar soluciones concisas, eficaces y menos propensas a errores.
La capacidad de escribir y utilizar cierres JavaScript es, por tanto, una habilidad esencial para los desarrolladores JavaScript de hoy en día. Son un resultado natural de la forma en que funciona JavaScript, con funciones de primera clase, ámbito y entornos léxicos. Por lo tanto, al dominar los cierres de JavaScript, profundizas aún más en tu comprensión de JavaScript en su conjunto, sentando las bases para convertirte en un desarrollador competente.
Cierres de Javascript - Puntos clave
- Cierres de Javascript: Funciones que tienen acceso al ámbito padre, incluso después de que la función padre se haya cerrado. Se utilizan para la privacidad de los datos y la encapsulación en JavaScript.
- Fábrica de funciones: Una función como makeAdder en el texto que devuelve dos nuevas funciones basadas en parámetros de entrada. Las fábricas de funciones son un caso de uso común para los cierres de JavaScript.
- Ámbito/Cierre Privado: En el contexto de los cierres de JavaScript, significa determinadas variables o funciones que sólo existen dentro de la función anónima, formando un cierre, y a las que no se puede acceder desde el exterior. Esta técnica es habitual en la creación de privacidad de datos.
- Retraso en la ejecución de funciones: Se puede retrasar la ejecución de una función utilizando cierres. Puede ser en escuchadores de eventos, funciones setTimeOut o llamadas AJAX.
- Emulación y encapsulación de objetos: Los cierres de JavaScript pueden utilizarse para emular objetos en el lenguaje, y encapsular o envolver datos y métodos para limitar la contaminación del espacio de nombres global y las modificaciones accidentales, proporcionando privacidad a los datos.
Aprende más rápido con las 15 tarjetas sobre Cierres de Javascript
Regístrate gratis para acceder a todas nuestras tarjetas.
Preguntas frecuentes sobre Cierres de Javascript
Acerca de StudySmarter
StudySmarter es una compañía de tecnología educativa reconocida a nivel mundial, que ofrece una plataforma de aprendizaje integral diseñada para estudiantes de todas las edades y niveles educativos. Nuestra plataforma proporciona apoyo en el aprendizaje para una amplia gama de asignaturas, incluidas las STEM, Ciencias Sociales e Idiomas, y también ayuda a los estudiantes a dominar con éxito diversos exámenes y pruebas en todo el mundo, como GCSE, A Level, SAT, ACT, Abitur y más. Ofrecemos una extensa biblioteca de materiales de aprendizaje, incluidas tarjetas didácticas interactivas, soluciones completas de libros de texto y explicaciones detalladas. La tecnología avanzada y las herramientas que proporcionamos ayudan a los estudiantes a crear sus propios materiales de aprendizaje. El contenido de StudySmarter no solo es verificado por expertos, sino que también se actualiza regularmente para garantizar su precisión y relevancia.
Aprende más