Alcance y cierres

En JavaScript, el alcance es el contexto en el que se ejecuta el código. Hay tres tipos de alcance: alcance global, alcance local (a veces denominado "alcance de función") y alcance de evaluación.

Código definido utilizando var el interior de una función tiene un ámbito local, y solo es "visible" para otras expresiones en esa función, que incluye el código dentro de cualquier función anidada / secundaria. Se puede acceder a las variables definidas en el alcance global desde cualquier lugar porque es el nivel más alto y la última parada en la cadena de alcance.

Examine el código que sigue y asegúrese de comprender que cada declaración de foo es único por su alcance.

Muestra: sample110.html

 

Asegúrate de entender que cada foo la variable contiene un valor diferente porque cada uno está definido en un ámbito específicamente delineado.

Se puede crear un número ilimitado de funciones y ámbitos eval, mientras que un entorno JavaScript solo utiliza un ámbito global.

El alcance global es la última parada en la cadena de alcance..

Las funciones que contienen funciones crean ámbitos de ejecución apilados. Estas pilas, que están encadenadas, a menudo se conocen como la cadena de alcance.


JavaScript no tiene ámbito de bloqueo

Dado que las declaraciones lógicas (Si) y declaraciones de bucle (para) no crean un alcance, las variables pueden sobrescribirse unas a otras. Examine el siguiente código y asegúrese de entender que el valor de foo Se está redefiniendo a medida que el programa ejecuta el código..

Muestra: sample111.html

 

Asi que foo está cambiando a medida que se ejecuta el código porque JavaScript no tiene una función de bloqueo de alcance único, alcance global o eval.


Utilizar var Dentro de las funciones para declarar variables y evitar alcances de alcance

JavaScript declarará cualquier variable que carezca de var declaración (incluso aquellas contenidas en una función o funciones encapsuladas) para estar en el alcance global en lugar del alcance local previsto. Eche un vistazo al código que sigue y observe que sin el uso de var para declarar barra, la variable se define realmente en el ámbito global y no en el ámbito local, donde debería estar.

Muestra: sample112.html

 

El concepto para llevar aquí es que siempre debes usar var Al definir variables dentro de una función. Esto evitará que resuelva problemas de alcance potencialmente confusos. La excepción a esta convención, por supuesto, es cuando desea crear o cambiar propiedades en el ámbito global desde una función..


La cadena de alcance (también conocido como alcance léxico)

Hay una cadena de búsqueda que se sigue cuando JavaScript busca el valor asociado a una variable. Esta cadena se basa en la jerarquía de alcance. En el código que sigue, estoy registrando el valor de sayHiText desde el func2 alcance de la función.

Muestra: sample113.html

 

Como es el valor de sayHiText encontrado cuando no está contenido dentro del alcance de la func2 ¿función? JavaScript primero mira en el func2 función para una variable llamada sayHiText. No encontrando func2 allí, mira hacia arriba func2función principal, func1. los sayHiText variable no se encuentra en el func1 alcance, ya sea, por lo que JavaScript continúa hasta el alcance global donde sayHiText se encuentra, en cuyo punto el valor de sayHiText está entregado. Si sayHiText No se había definido en el ámbito global., indefinido habría sido devuelto por JavaScript.

Este es un concepto muy importante para entender. Examinemos otro ejemplo de código, uno en el que tomamos tres valores de tres ámbitos diferentes.

Muestra: sample114.html

 

El valor para z es local al bar función y el contexto en el que el console.log se invoca El valor para y está en el foo función, que es el padre de bar(), y el valor para X Está en el ámbito global. Todos estos son accesibles a la bar Funcionar a través de la cadena de alcance. Asegúrese de que entiende que las variables de referencia en el bar La función revisará todo el camino hasta la cadena de alcance para las variables a las que se hace referencia.

La cadena de alcance, si lo piensas, no es tan diferente de la cadena del prototipo. Ambos son simplemente una forma de buscar un valor al verificar un conjunto sistemático y jerárquico de ubicaciones.


La búsqueda en la cadena de alcance devuelve el primer valor encontrado

En el ejemplo de código que sigue, una variable llamada X Existe en el mismo ámbito en el que se examina con console.log. Este valor "local" de X se utiliza, y se podría decir que sombrea, o máscaras, el nombre idéntico X Las variables se encuentran más arriba en la cadena de alcance..

Muestra: sample115.html

 

Recuerde que la búsqueda de alcance finaliza cuando la variable se encuentra en el enlace disponible más cercano de la cadena, incluso si el mismo nombre de variable se usa más arriba en la cadena.


El alcance se determina durante la definición de la función, no la invocación

Como las funciones determinan que el alcance y las funciones se pueden pasar como cualquier valor de JavaScript, se podría pensar que descifrar la cadena de alcance es complicado. En realidad es muy simple. La cadena de alcance se decide en función de la ubicación de una función durante la definición, no durante la invocación. Esto también se llama alcance léxico. Piense mucho en esto, ya que la mayoría de las personas se tropieza con él con frecuencia en el código JavaScript..

La cadena de alcance se crea antes de invocar una función. Debido a esto, podemos crear cierres. Por ejemplo, podemos hacer que una función devuelva una función anidada al ámbito global, pero nuestra función aún puede acceder, a través de la cadena de alcance, al alcance de su función principal. En la siguiente muestra, definimos una función de los padres que devuelve una función anónima, y ​​llamamos a la función devuelta desde el ámbito global. Porque nuestra función anónima fue definida como contenida dentro de función de los padres, todavía tiene acceso a funciones de los padres alcance cuando se invoca. Esto se llama un cierre.

Muestra: sample116.html

 

La idea que debe quitar aquí es que la cadena de alcance se determina durante la definición, literalmente, en la forma en que se escribe el código. Pasar las funciones dentro de su código no cambiará la cadena de alcance.


Los cierres son causados ​​por la cadena de alcance

Tome lo que ha aprendido sobre la búsqueda de alcance y cadena de alcance de este artículo, y un cierre no debería ser demasiado complicado de entender. En el siguiente ejemplo, creamos una función llamada CountUpFromZero. Esta función en realidad devuelve una referencia a la función secundaria contenida en ella. Cuando se invoca esta función secundaria (función anidada), todavía tiene acceso al alcance de la función principal debido a la cadena de alcance.

Muestra: sample117.html

 

Cada vez que el CountUpFromZero se invoca la función, la función anónima contenida en (y devuelta desde) la CountUpFromZero La función todavía tiene acceso al ámbito de la función principal. Esta técnica, facilitada a través de la cadena de alcance, es un ejemplo de cierre..


Conclusión

Si sientes que tengo cierres demasiado simplificados, es probable que tengas razón en este pensamiento. Pero lo hice a propósito, ya que creo que las partes importantes provienen de una sólida comprensión de las funciones y el alcance, no necesariamente las complejidades del contexto de ejecución. Si necesita una inmersión profunda en los cierres, eche un vistazo a los cierres de JavaScript.