Leí páginas de MDN sobre const , let , var . el resumen de eso es antes de ES2015 , solo tenemos global scope de function scope . En [esta página de MDN] [1] hay un ejemplo de los beneficios del alcance de bloque; que muestra: en lugar de usar el concepto de cierre para guardar datos relacionados para una función, como para el número de iteración del bucle, definió la variable de bucle como let . si la palabra clave let es solo para el alcance de bloques, ¿cómo nos proporciona esta funcionalidad? ¿Hay otros lenguajes de programación que tengan este concepto?
let divClassX = document.querySelectorAll('.x'); for (let j = 0; j < 2; j++) { divClassX[j].onclick = function (event) { console.log('class x div\'sx ' + j) } }El código anterior tiene la misma funcionalidad que:
let divClassX = document.querySelectorAll('.x'); for (var j = 0; j < 2; j++) { divClassX[j].onclick = (function (j) { return function (event) { console.log('class x div\'sx ' + j) } })(j) }Asumí que existe alguna funcionalidad como esa, por lo que el código de soplado debe funcionar como el anterior, pero cuando hice clic en div1 o div2 en ambas ocasiones, obtuve 2, pero esperaba uno cuando hice clic en div 1 y dos cuando hice clic en div2.
let div1 = document.querySelector('#div1'); let div2 = document.querySelector('#div2'); let i = 1; div1.onclick = function (event) { console.log(i); } i = i + 1; div2.onclick = function (event) { console.log(i); }¿Qué concepto existe que no conozco? [1]: https://developer.mozilla.org/en-US/docs/Glossary/IIFE
Se trata más del ámbito en el que se define la variable que del orden en que se modifica.
En su último ejemplo, let i ocurra en el ámbito global. Cada function que crea como detector de eventos crea su propio ámbito cuyo ámbito principal es el ámbito global. No importa cuál era el valor de i cuando se creó la función, lo que importa es la estructura de la cadena de alcance. JavaScript busca variables en ámbitos cada vez más grandes que suben por la "cadena" de ámbitos principales. Para ambas funciones i resolveré el alcance global cuando se acceda en el momento en que se llama a la función , no cuando se crea la función.
En cuanto a los bucles con let , creo que parte del objetivo de diseño de let era hacer que el comportamiento del controlador de eventos/bucles (u otras funciones anidadas) fuera más intuitivo y proporcionar una manera fácil de evitar el problema común en el que cada controlador de eventos hace referencia al último valor de i en oposición al valor cuando se creó la función (es decir, en cada iteración del ciclo).
En otras palabras, en ES2015 hay un alcance separado para cada iteración del ciclo, y let asigna variables a ese alcance, no a la function circundante o al alcance global como var . Además, cuando se llama a una función anidada (una función que está dentro del bucle for ), primero toca el alcance de "iteración" al buscar la cadena de alcance, por lo que ve la i tal como estaba en el momento de la iteración.
Se llama cierre .
Un cierre es la combinación de una función agrupada (encerrada) con referencias a su estado circundante (el entorno léxico). En otras palabras, un cierre le da acceso al alcance 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 la creación de la función.
En tu último fragmento
console.log(i); no imprime una copia, sino la variable real i (referencia), que se inicializa con
let i = 1;y modificado con
i = i + 1;