¿Cómo funcionan los bloqueadores de javascript?

¿Cómo explicaría el cierre de JavaScript para alguien que tiene conocimiento de los conceptos de los que están compuestos (por ejemplo, funciones, variables, etc.), pero no comprende los cierres en sí mismos?

Vi un ejemplo del esquema dado en Wikipedia, pero, desafortunadamente, no ayudó.

7654
21 сент. configurado a e-satis el 21 sept. 2008-09-21 17:12 '08 a las 5:12 pm 2008-09-21 17:12
@ 89 respuestas
  • 1
  • 2
  • 3

Cierre de javascript para principiantes.

Enviado por Morris el martes, 2006-02-21 10:19. La comunidad ha sido editada desde entonces.

El cierre no es magia

Esta página explica el cierre para que el programador pueda entenderlos, utilizando el código JavaScript de trabajo. Esto no es para gurús o programadores funcionales.

El cierre no es difícil de entender tan pronto como se cose el concepto básico. Sin embargo, no se pueden entender mediante la lectura de explicaciones teóricas o académicas.

Este artículo está dirigido a programadores con cierta experiencia en programación básica y puede leer la siguiente función de JavaScript:

primera clase ;  es una expresión que puede referirse a las variables dentro de su alcance (cuando se declaró anteriormente), asignarse a una variable, pasar como un argumento de función o devolverse como el resultado de una función. 

Ejemplo de cierre

El siguiente código devuelve una referencia de función:

 function say667() { // Local variable that ends up within closure var num = 42; var say = function() { console.log(num); } num++; return say; } var sayNumber = say667(); sayNumber(); // logs 43 

Ejemplo 4

Las tres funciones globales tienen una referencia común al mismo cierre, ya que todas se declaran durante una sola llamada a setupSomeGlobals() .

 function sayAlice() { var say = function() { console.log(alice); } // Local variable that ends up within closure var alice = 'Hello Alice'; return say; } sayAlice()();// logs "Hello Alice" 

Difícil: también tenga en cuenta, say variable say también está dentro del cierre, y puede decir sayAlice() cualquier otra función que se pueda declarar en sayAlice() , o se puede obtener recursivamente dentro de una función interna.

Ejemplo 6

Esta es una verdadera magia para todas las personas, por lo que necesitas entenderla. Tenga mucho cuidado si define una función dentro de un bucle: es posible que las variables locales del cierre no actúen como podría pensar.

Debe comprender la función de "elevación variable" de javascript para comprender este ejemplo.

 function newClosure(someNum, someRef) { // Local variables that end up within closure var num = someNum; var anArray = [1,2,3]; var ref = someRef; return function(x) { num += x; anArray.push(num); console.log('num: ' + num + '; anArray: ' + anArray.toString() + '; ref.someVar: ' + ref.someVar + ';'); } } obj = {someVar: 4}; fn1 = newClosure(4, obj); fn2 = newClosure(5, obj); fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4; fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4; obj.someVar++; fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5; fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5; 

Resumen

Si todo parece completamente incierto, es mejor jugar con ejemplos. Leer explicaciones es mucho más difícil que entender ejemplos. Mis explicaciones para cierres y apilamientos, etc. No son técnicamente correctos, son simplificaciones básicas diseñadas para ayudar a comprender. Una vez resuelta la idea básica, puede obtener los detalles más adelante.

Puntos finales:

  • Cuando se utiliza la function dentro de otra función, se utiliza el cierre.
  • Siempre que use eval() dentro de una función, se usa un cierre. El texto que eval puede referirse a las variables locales de una función, y en eval incluso puede crear nuevas variables locales con eval('var foo = …')
  • Cuando utiliza la new Function(…) ( constructor de función ) dentro de una función, no crea un cierre. (La nueva función no puede referirse a las variables locales de la función externa).
  • Cerrar en JavaScript es como mantener una copia de todas las variables locales, como cuando se sale de una función.
  • Probablemente es mejor pensar que el cierre siempre se crea como una entrada de función, y se agregan variables locales a este cierre.
  • Se guarda un nuevo conjunto de variables locales cada vez que se llama a una función con un cierre (dado que la función contiene una declaración de función dentro de ella, o si la referencia a esta función interna se devuelve o la referencia externa se almacena de alguna manera).
  • Dos funciones pueden parecer que tienen el mismo código fuente, pero tienen un comportamiento completamente diferente debido a su cierre oculto. No creo que el código JavaScript realmente pueda descubrir si la función tiene un cierre de enlace o no.
  • Si intenta realizar algún cambio en el código fuente dinámico (por ejemplo: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola')); ), no funcionará si myFunction es un cierre (por supuesto, no pensaría en reemplazar las líneas de origen en tiempo de ejecución, pero ...).
  • Puede obtener las declaraciones de funciones dentro de las declaraciones de funciones dentro de las funciones de mdash, y puede obtener el cierre en más de un nivel.
  • Creo que normalmente el cierre es un término tanto para una función como para variables capturadas. Tenga en cuenta que no utilizo esta definición en este artículo.
  • Sospecho que los cierres en JavaScript son diferentes de los que se encuentran comúnmente en los lenguajes funcionales.

conexiones

gracias a

Si acaba de enterarse del cierre (¡aquí o en otro lugar!), Entonces me interesa cualquier comentario que tenga sobre cualquier cambio que pueda sugerir para aclarar este artículo. Enviar un mensaje a morrisjohns.com (morris_closure @). Tenga en cuenta que no soy un gurú de JavaScript, no al final.


La publicación original de Morris se puede encontrar en el archivo de Internet .

6329
21 сент. Respuesta dada por Joel Anair el 21 de septiembre. 2008-09-21 17:18 '08 a las 17:18 2008-09-21 17:18

Cuando vea la palabra clave de la función en otra función, la función interna tendrá acceso a las variables en la función externa.

 function foo(x) { var tmp = 3; return function (y) { console.log(x + y + (++tmp)); // will also log 16 } } var bar = foo(2); // bar is now a closure. bar(10); 

La función anterior también escribirá 16, porque la bar aún puede referirse a x y tmp , incluso si ya no está dentro de la región.

Sin embargo, dado que tmp todavía cuelga alrededor del cierre de la bar interior, también aumenta. Aumentará cada vez que llames bar .

El ejemplo más simple de un cierre es el siguiente:

border=0

 function foo(x) { var tmp = 3; return function (y) { console.log(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; console.log(x.memb); } } var age = new Number(2); var bar = foo(age); // bar is now a closure referencing age. bar(10); 

Como se esperaba, cada llamada a la bar(10) incrementará x.memb . ¡No puede esperar que x refiera simplemente al mismo objeto que la variable de age ! Después de un par de llamadas a bar age.memb habrá 2! Este enlace sirve como base para las fugas de memoria con objetos HTML.

3825
21 сент. Respuesta dada a Ali el 21 de septiembre. 2008-09-21 18:16 '08 a las 6:16 pm 2008-09-21 18:16

PRÓLOGO: esta respuesta fue escrita cuando la pregunta era:

Al igual que el viejo Albert, dijo: "Si no puede explicárselo a un niño de seis años, usted mismo no entiende". Bueno, traté de explicarle el cierre de JS a un amigo de 27 años y fracasé completamente.

¿Alguien podría pensar que tengo 6 años y que estoy extrañamente interesado en este problema?

Estoy bastante seguro de que fui una de esas personas que intentaron tomar la pregunta inicial literalmente. Desde entonces, esta pregunta ha sido mutada varias veces, por lo que mi respuesta ahora puede parecer increíblemente estúpida e inapropiada. Espero que la idea general de esta historia siga siendo interesante.


Soy un gran fanático de las analogías y las metáforas para explicar conceptos complejos, así que permítame probar la historia.

Érase una vez:

Había una princesa ...

 function princess() { 

Vivía en un maravilloso mundo lleno de aventuras. Conoció a su príncipe Carlos, recorrió su mundo en un unicornio, luchó con dragones, se reunió con animales que hablaban y muchas otras cosas fantásticas.

  var adventures = []; function princeCharming() {  } var unicorn = {  }, dragons = [  ], squirrel = "Hello!";  

Pero ella siempre tenía que regresar a su aburrido mundo de problemas y adultos.

  return { 

Y a menudo les contaba sobre su última aventura increíble como princesa.

  story: function() { return adventures[adventures.length - 1]; } }; } 

Pero todo lo que vieron fue una niña ...

 var littleGirl = princess(); 

... contando historias sobre magia y fantasía.

 littleGirl.story(); 

Y mientras los adultos sabían sobre las princesas reales, nunca habrían creído en los unicornios o los dragones, porque nunca los vieron. Los adultos dijeron que existen solo dentro de la imaginación de una niña.

Pero sabemos la verdad verdadera; que una niña con una princesa dentro ...

... en realidad una princesa con una niña pequeña dentro.

2273
24 июня '11 в 21:49 2011-06-24 21:49 Jacob Swartwood da la respuesta el 24 de junio de 2011 a las 21:49 2011-06-24 21:49

Tomando en serio esta pregunta, necesitamos descubrir que una persona típica de 6 años de edad tiene capacidad cognitiva, aunque hay que reconocer que las personas interesadas en JavaScript no son tan típicas.

Sobre el desarrollo de la infancia: de 5 a 7 años se dice:

Su hijo podrá seguir instrucciones de dos pasos. Por ejemplo, si le dice a su hijo: "Vaya a la cocina y tome una bolsa de basura", pueden recordar esta dirección.

Podemos usar este ejemplo para explicar los cierres de la siguiente manera:

Una cocina es un cierre en el que hay una variable local llamada trashBags . Dentro de la cocina hay una función getTrashBag que recibe una bolsa de basura y la devuelve.

Podemos codificar esto en javascript de la siguiente manera:

696
02 сент. la respuesta se da dlaliberte 02 sep . 2011-09-02 18:23 '11 a las 18:23 2011-09-02 18:23

Hombre de paja

Necesito saber cuántas veces se presiona el botón y hacer algo con cada tercer clic ...

Solución bastante obvia

 <button id="button">Click Me!</button> 

Теперь это будет работать, но оно вторгается во внешнюю область, добавляя переменную, единственной целью которой является отслеживание счета. В некоторых ситуациях это было бы предпочтительнее, так как вашему внешнему приложению может потребоваться доступ к этой информации. Но в этом случае мы меняем только каждый третий клик, поэтому рекомендуется включать эту функциональность внутри обработчика событий .

Рассмотрим этот вариант

 <button id="button">Click Me!</button>