Estoy haciendo todo lo posible para comprender los cierres de JavaScript.
Entiendo que al devolver una función interna, tendrá acceso a cualquier variable definida en su elemento primario inmediato.
¿Dónde me sería útil? Tal vez todavía no lo he entendido. La mayoría de los ejemplos que he visto en línea no proporcionan ningún código del mundo real, solo ejemplos vagos.
¿Alguien puede mostrarme un uso real de un cierre?
¿Es este, por ejemplo?
var warnUser = function (msg) {
var calledCount = 0;
return function() {
calledCount++;
alert(msg + '\nYou have been warned ' + calledCount + ' times.');
};
};
var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
Respuestas:
He usado cierres para hacer cosas como:
Como puede ver allí,
a
ahora es un objeto, con un métodopublicfunction
(a.publicfunction()
) que llamaprivatefunction
, que solo existe dentro del cierre. NO puede llamarprivatefunction
directamente (es decira.privatefunction()
), solopublicfunction()
.Es un ejemplo mínimo, pero ¿tal vez puedas ver sus usos? Usamos esto para imponer métodos públicos / privados.
fuente
Supongamos que desea contar la cantidad de veces que el usuario hizo clic en un botón en una página web.
Para esto, está activando una función en
onclick
caso de botón para actualizar el recuento de la variableAhora podría haber muchos enfoques como:
1) Podría usar una variable global y una función para aumentar el contador :
Pero, la trampa es que cualquier script en la página puede cambiar el contador, sin llamar
updateClickCount()
.2) Ahora, puede estar pensando en declarar la variable dentro de la función:
¡Pero hey! Cada vez
updateClickCount()
que se llama a la función, el contador se establece nuevamente en 1.3) ¿Pensando en funciones anidadas ?
Las funciones anidadas tienen acceso al alcance "encima" de ellas.
En este ejemplo, la función interna
updateClickCount()
tiene acceso a la variable de contador en la función primariacountWrapper()
Esto podría haber resuelto el dilema del contador, si pudiera alcanzar la
updateClickCount()
función desde el exterior y también necesita encontrar una manera de ejecutarcounter = 0
solo una vez, no siempre.4) ¡ Cierre al rescate! (función de auto invocación) :
La función de invocación automática solo se ejecuta una vez. Establece el
counter
cero (0) y devuelve una expresión de función.De esta manera se
updateClickCount
convierte en una función. La parte "maravillosa" es que puede acceder al contador en el ámbito principal.Esto se llama cierre de JavaScript . Permite que una función tenga variables " privadas ".
¡
counter
Está protegido por el alcance de la función anónima y solo se puede cambiar con la función de agregar!Ejemplo más animado sobre el cierre:
Referencia: https://www.w3schools.com/js/js_function_closures.asp
fuente
El ejemplo que das es excelente. Los cierres son un mecanismo de abstracción que le permite separar las preocupaciones de manera muy limpia. Su ejemplo es un caso de separación de instrumentación (conteo de llamadas) de semántica (una API de informe de errores). Otros usos incluyen:
Pasar el comportamiento parametrizado a un algoritmo (programación clásica de orden superior):
Simulación de programación orientada a objetos:
Implementación de control de flujo exótico, como el manejo de eventos de jQuery y las API AJAX.
fuente
int
?) La última vez que lo comprobé, JavaScript era un lenguaje de tipo pato. ¿Quizás estabas pensando en Java?Sé que llegué muy tarde al responder esta pregunta, pero podría ayudar a cualquiera que todavía esté buscando la respuesta en 2018.
Los cierres de Javascript se pueden usar para implementar la funcionalidad de aceleración y antirrebote en su aplicación.
Estrangulamiento :
La limitación establece un límite como la cantidad máxima de veces que se puede invocar una función a lo largo del tiempo. Como en "ejecutar esta función como máximo una vez cada 100 milisegundos".
Código:
Rebote :
El rebote pone un límite a una función que no se volverá a llamar hasta que haya transcurrido una cierta cantidad de tiempo sin que se llame. Como en "ejecutar esta función solo si han pasado 100 milisegundos sin que se llame".
Código:
Como puede ver, los cierres ayudaron a implementar dos hermosas características que cada aplicación web debería tener para proporcionar una funcionalidad de experiencia de interfaz de usuario fluida.
Espero que ayude a alguien.
fuente
Sí, ese es un buen ejemplo de un cierre útil. La llamada a warnUser crea la
calledCount
variable en su alcance y devuelve una función anónima que se almacena en lawarnForTamper
variable. Debido a que todavía hay un cierre que hace uso de la variable calledCount, no se elimina al salir de la función, por lo que cada llamada alwarnForTamper()
aumentará la variable de ámbito y alertará el valor.El problema más común que veo en StackOverflow es cuando alguien quiere "retrasar" el uso de una variable que se incrementa en cada ciclo, pero debido a que la variable tiene un alcance, cada referencia a la variable sería después de que el ciclo haya terminado, lo que resulta en estado final de la variable:
Esto daría como resultado que cada alerta muestre el mismo valor de
i
, el valor al que se incrementó cuando finalizó el ciclo. La solución es crear un nuevo cierre, un alcance separado para la variable. Esto se puede hacer usando una función anónima ejecutada instantáneamente, que recibe la variable y almacena su estado como argumento:fuente
En el lenguaje JavaScript (o cualquier ECMAScript), en particular, los cierres son útiles para ocultar la implementación de la funcionalidad y al mismo tiempo revelar la interfaz.
Por ejemplo, imagine que está escribiendo una clase de métodos de utilidad de fecha y desea permitir que los usuarios busquen nombres de días de la semana por índice, pero no desea que puedan modificar la matriz de nombres que usa debajo del capó.
Tenga en cuenta que la
days
matriz podría simplemente almacenarse como una propiedad deldateUtil
objeto, pero luego sería visible para los usuarios de la secuencia de comandos e incluso podrían cambiarla si quisieran, sin siquiera necesitar su código fuente. Sin embargo, dado que está encerrado por la función anónima que devuelve la función de búsqueda de fecha, solo es accesible por la función de búsqueda, por lo que ahora es a prueba de manipulaciones.fuente
Hay una sección sobre cierres prácticos en la red de desarrolladores de Mozilla .
fuente
return function ()...
el código todavía funciona bien. El cierre no es una guaridaOtro uso común para los cierres es enlazar
this
un método a un objeto específico, lo que permite que se llame a otro lugar (como un controlador de eventos).Cada vez que se dispara un evento mousemove,
watcher.follow(evt)
se llama.Los cierres también son una parte esencial de las funciones de orden superior, ya que permiten el patrón muy común de reescribir múltiples funciones similares como una sola función de orden superior al parametrizar las porciones diferentes. Como un ejemplo abstracto,
se convierte
donde A y B no son unidades sintácticas sino cadenas de código fuente (no literales de cadena).
Consulte " Simplificar mi javascript con una función " para ver un ejemplo concreto.
fuente
Aquí, tengo un saludo que quiero decir varias veces. Si creo un cierre, simplemente puedo llamar a esa función para grabar el saludo. Si no creo el cierre, tengo que pasar mi nombre cada vez.
Sin cierre ( https://jsfiddle.net/lukeschlangen/pw61qrow/3/ ):
Con un cierre ( https://jsfiddle.net/lukeschlangen/Lb5cfve9/3/ ):
fuente
Si se siente cómodo con el concepto de instanciar una clase en el sentido orientado a objetos (es decir, crear un objeto de esa clase), entonces está cerca de comprender los cierres.
Piénselo de esta manera: cuando crea una instancia de dos objetos Persona, sabe que la variable de miembro de la clase "Nombre" no se comparte entre las instancias; cada objeto tiene su propia 'copia'. De manera similar, cuando crea un cierre, la variable libre ('llamadaCount' en su ejemplo anterior) está vinculada a la 'instancia' de la función.
Creo que su salto conceptual se ve ligeramente obstaculizado por el hecho de que cada función / cierre devuelto por el cierre de la función warnUser (aparte: esa es una función de orden superior ) se une a 'calledCount' con el mismo valor inicial (0), mientras que a menudo al crear cierres es más útil pasar diferentes inicializadores a la función de orden superior, al igual que pasar valores diferentes al constructor de una clase.
Entonces, suponga que cuando 'calledCount' alcanza un cierto valor que desea finalizar la sesión del usuario; es posible que desee valores diferentes para eso, dependiendo de si la solicitud proviene de la red local o del gran Internet malo (sí, es un ejemplo artificial). Para lograr esto, puede pasar diferentes valores iniciales para calledCount a warnUser (es decir, -3 o 0?).
Parte del problema con la literatura es la nomenclatura utilizada para describirlos ("alcance léxico", "variables libres"). No dejes que te engañe, los cierres son más simples de lo que parece ... prima facie ;-)
fuente
Aquí tengo un ejemplo simple del concepto de cierre que podemos usar en nuestro sitio de comercio electrónico o en muchos otros también. Estoy agregando mi enlace jsfiddle con el ejemplo. contiene una pequeña lista de productos de 3 artículos y un mostrador de carrito.
Jsfiddle
fuente
Uso de cierres:
Los cierres son una de las características más potentes de JavaScript. JavaScript permite el anidamiento de funciones y otorga a la función interna acceso total a todas las variables y funciones definidas dentro de la función externa (y a todas las demás variables y funciones a las que tiene acceso la función externa). Sin embargo, la función externa no tiene acceso a las variables y funciones definidas dentro de la función interna. Esto proporciona una especie de seguridad para las variables de la función interna. Además, dado que la función interna tiene acceso al alcance de la función externa, las variables y funciones definidas en la función externa vivirán más tiempo que la función externa en sí, si la función interna logra sobrevivir más allá de la vida de la función externa.
Ejemplo:
En el código anterior, la variable de nombre de la función externa es accesible para las funciones internas, y no hay otra forma de acceder a las variables internas, excepto a través de las funciones internas. Las variables internas de la función interna actúan como almacenes seguros para las funciones internas. Contienen datos "persistentes", pero seguros, para que funcionen las funciones internas. Las funciones ni siquiera tienen que asignarse a una variable, o tener un nombre. lea aquí para más detalles
fuente
Me gusta el ejemplo de fábrica de funciones de Mozilla .
fuente
El patrón del módulo de JavaScript utiliza cierres. Su bonito patrón le permite tener algo parecido a vars "públicos" y "privados".
fuente
Hace un tiempo escribí un artículo sobre cómo se pueden usar los cierres para simplificar el código de manejo de eventos. Compara el manejo de eventos ASP.NET con jQuery del lado del cliente.
http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/
fuente
Este hilo me ha ayudado enormemente a comprender mejor cómo funcionan los cierres. Desde entonces, he experimentado un poco por mi cuenta y se me ocurrió este código bastante simple que puede ayudar a otras personas a ver cómo los cierres se pueden usar de manera práctica y cómo usar el cierre en diferentes niveles para mantener variables similares a la estática y / o variables globales sin riesgo de sobrescribirlas o confundirlas con variables globales. Lo que esto hace es realizar un seguimiento de los clics de los botones, tanto a nivel local para cada botón individual como a nivel global, contando cada clic de botón, contribuyendo a una sola figura. Tenga en cuenta que no he usado ninguna variable global para hacer esto, lo cual es una especie de objetivo del ejercicio: tener un controlador que se pueda aplicar a cualquier botón que también contribuya a algo globalmente.
Por favor, expertos, ¡háganme saber si he cometido alguna mala práctica aquí! Todavía estoy aprendiendo esto por mí mismo.
fuente
Referencia: uso práctico de cierres
En la práctica, los cierres pueden crear diseños elegantes, lo que permite la personalización de varios cálculos, llamadas diferidas, devoluciones de llamada, creación de alcance encapsulado, etc.
Un ejemplo del método de clasificación de matrices que acepta como argumento la función de condición de clasificación:
Mapeo funcional como el método de mapeo de matrices que mapea una nueva matriz por la condición del argumento funcional:
A menudo es conveniente implementar funciones de búsqueda utilizando argumentos funcionales que definen condiciones casi ilimitadas para la búsqueda:
Además, podemos observar la aplicación de funciones como, por ejemplo, un método forEach que aplica una función a una matriz de elementos:
Se aplica una función a los argumentos (a una lista de argumentos - en apply, y a argumentos posicionados - en llamada):
Llamadas diferidas:
Funciones de devolución de llamada:
Creación de un alcance encapsulado con el propósito de ocultar objetos auxiliares:
fuente
Violín
fuente
Los cierres son una forma útil de crear generadores, una secuencia incrementada bajo demanda:
Las diferencias se resumen de la siguiente manera:
Referencias
fuente
En la muestra dada, el valor de la variable adjunta 'contador' está protegido y solo puede modificarse utilizando las funciones dadas (incremento, decremento). porque está en un cierre,
fuente
Explicando el uso práctico de un Cierre en JavaScript ---
Cuando creamos una función dentro de otra función, estamos creando un cierre. Los cierres son poderosos porque son capaces de leer y manipular los datos de sus funciones externas. Cada vez que se invoca una función, se crea un nuevo ámbito para esa llamada. La variable local declarada dentro de la función pertenece a ese ámbito y solo se puede acceder desde esa función. Cuando la función ha finalizado la ejecución, el alcance generalmente se destruye.
Un ejemplo simple de tal función es este:
En el ejemplo anterior, la función buildName () declara un saludo de variable local y lo devuelve. Cada llamada a una función crea un nuevo ámbito con una nueva variable local. Una vez que la función termina de ejecutarse, no tenemos forma de volver a referirnos a ese alcance, por lo que se recolecta basura.
Pero, ¿qué tal cuando tenemos un enlace a ese alcance?
Veamos la siguiente función:
La función sayName () de este ejemplo es un cierre. La función sayName () tiene su propio ámbito local (con variable de bienvenida) y también tiene acceso al ámbito de la función externa (que lo encierra). En este caso, el saludo variable de buildName ().
Una vez realizada la ejecución de buildName, el alcance no se destruye en este caso. La función sayMyName () todavía tiene acceso a ella, por lo que no se recolectará basura. Sin embargo, no hay otra forma de acceder a los datos desde el ámbito externo, excepto el cierre. El cierre sirve como la puerta de entrada entre el contexto global y el alcance externo.
fuente
Estoy tratando de aprender clousures y creo que el ejemplo que he creado es un caso de uso práctico. Puede ejecutar el fragmento y ver el resultado en la consola. Tenemos dos usuarios separados que tienen datos separados. Cada uno de ellos puede ver el estado real y actualizarlo.
fuente