Aquí hay un ejemplo simple, donde dos botones se agregan dinámicamente a un elemento DIV:
Buttons:
function addButton (name, message, parentId) { var b = document.createElement("INPUT"); b.type = "button"; b.value = name; b.onclick = function() { alert (message); } document.getElementById(parentId).appendChild (b); } addButton("button 1", "hello world", 'container'); addButton("button 2", "goodbye world", 'container');
El código anterior creará dos botones, y cuando haga clic en ellos, cada uno mostrará un mensaje diferente (“hola mundo” y “adiós mundo”). El mensaje variable (pasado como argumento para addButton () ), es visible dentro de la función anónima establecida como el clic de cada botón.
Cuando se llama a la función onclick (debido a que un usuario hace clic en el botón, lo que podría pasar mucho tiempo después), esa función puede ver el valor del mensaje variable, aunque la función addButton () que contiene esa variable, regresó hace mucho tiempo .
- ¿Cómo genera música la computadora? ¿Qué sucede dentro de la computadora para generar música?
- Computational Science (Scientific Computing): ¿Qué es la teoría funcional de la densidad (DFT)?
- ¿Cómo podría un pirata informático malicioso y hábil dañarme si quisiera?
- ¿Cómo difiere la ingeniería de software de la informática? ¿Son los dos aburridos?
- ¿Qué compañías en India están usando AngularJS en la producción?
De esta manera, los cierres permiten que las funciones se empaqueten junto con los datos . Aunque parece que los dos botones obtienen una función idéntica para su clic , las funciones no son realmente idénticas porque esas funciones “cierran” valores diferentes para el mensaje .
Hay otras formas en que un lenguaje podría lograr este tipo de cosas, pero la forma de usar los cierres de Javascript puede ser bastante útil.
Sin embargo, puede haber algunas desventajas confusas en el uso de cierres. Digamos que haces algo como esto:
Peligro: no es lo que esperas que pase aquí
function addButtons (howMany, parentId) { for (var i=1; i<=howMany; i++) { var b = document.createElement("INPUT"); b.type = "button"; b.value = "button " + i; b.onclick = function() { alert ("button " + i + " was clicked"); } document.getElementById(parentId).appendChild (b); } } addButtons(5, 'container');
Al ejecutar esto, se crean 5 botones, denominados “botón 1” a “botón 5”. Cuando hace clic en el primero … en lugar de decir “se hizo clic en el botón 1”, en su lugar dirá “se hizo clic en el botón 6”. Como todos ellos.
La razón es que en el momento en que se hace clic en el botón, la variable ‘i’ en realidad es 6. Una solución a esto, que se ve bastante fea, es crear e inmediatamente llamar a una función anónima de ajuste que devuelve su función onclick, así:
Esto funciona mucho mejor, pero es un poco confuso:
function addButtons (howMany, parentId) { for (var i=1; i<=howMany; i++) { var b = document.createElement("INPUT"); b.type = "button"; b.value = "button " + i; b.onclick = (function(which){ return function() { alert ("button " + which + " was clicked"); } })(i); document.getElementById(parentId).appendChild (b); } } addButtons(5, 'container');
Ahora, cada vez a través del ciclo, creará un nuevo contexto, cada uno de los cuales tiene una variable “cuál”, y cada uno tendrá valores diferentes (1-5). Entonces obtienes los resultados que esperas.