JS: Funciones
Teoría: Entorno

Si construyes una planta química, sería bueno aislarla del mundo exterior para evitar fugas de productos químicos. Podríamos decir que en este edificio hay su propio entorno - un microclima aislado del entorno externo.
En programación, este aislamiento se llama ámbito. En esta lección hablaremos sobre el entorno. Aprenderás sobre las diferentes zonas en las que se dividen los programas y cómo esto afecta el funcionamiento del código.
Ámbitos
Desde el punto de vista del entorno, los programas se dividen en dos ámbitos:
- Global (externo)
- Local (interno)
En el ámbito global se encuentra todo lo que creamos fuera de las funciones, instrucciones if, bucles y otros bloques de código:
En este ejemplo, la constante age, la función multiplier y la variable result tienen un ámbito global.
Hablemos más en detalle sobre la zona local de este ejemplo. Dentro de la función multiplier hay una constante x. Está dentro de un bloque de código y solo es visible dentro de esa función.
En la función multiplier también hay otro componente del ámbito local: el argumento num. No está definido tan claramente como las constantes o las variables, pero se comporta casi como una variable local.
No tenemos acceso a x desde el exterior, como si no existiera:
En este ejemplo, console.log se llama en el entorno global, pero x no está definido globalmente. Por lo tanto, obtenemos el mensaje de error Reference Error.
Intentemos definir x globalmente:
Ahora hay un x global. Imprimimos su valor en la pantalla, pero el x local dentro de la función multiplier sigue siendo visible solo dentro de esa función.
Estos dos x no tienen nada en común, están en diferentes ámbitos. No se fusionan en uno solo, a pesar de tener el mismo nombre.
Cualquier bloque de código entre llaves tiene un ámbito local. Aquí hay un ejemplo con un bloque if:
Lo mismo se aplica a los bucles while y for.
Ahora sabemos que lo local no está disponible desde el exterior y lo global está disponible en todas partes. ¿Incluso dentro de algo? Sí, y esto se puede ver en el siguiente ejemplo:
Esta variable global a cambió dentro de la función changer. La función hace algo solo cuando se llama, no cuando se define. Por lo tanto, al principio a es 0, pero después de llamar a changer, la variable a se convierte en 1.
Puede parecer conveniente poner todo en el ámbito global y olvidarse de las complicaciones. En realidad, esta es una práctica terrible. Las variables globales hacen que el código sea extremadamente frágil. Cualquier cosa puede romperse en este caso. Por lo tanto, evita el ámbito global y guarda las cosas donde pertenecen.
Ámbito léxico
Además del ámbito global y local, también existe el ámbito léxico. Es un mecanismo específico, una de las reglas para el ámbito que se aplica en JavaScript y en la mayoría de los otros lenguajes.
El ámbito léxico se puede entender simplemente como un mecanismo de búsqueda de valores: buscamos en el ámbito actual y, si no encontramos nada, subimos un nivel y así sucesivamente. La palabra "léxico" significa que la visibilidad se determina exclusivamente por el texto del programa.
En otras palabras, podemos mirar el texto del programa y saber el ámbito en cualquier punto. En otros lenguajes, puede haber un mecanismo no léxico, como el ámbito dinámico.
Veamos cómo funciona el ámbito léxico en la práctica. Echa un vistazo a este programa:
La función multiplier devuelve el producto de a y b. El valor de a está definido dentro de la función, pero b no.
Al intentar resolver la multiplicación a * b, JavaScript busca los valores de a y b. Comienza buscando localmente y se mueve hacia afuera un ámbito a la vez. Esto continúa hasta que JavaScript:
- Encuentra lo que necesita
- Ve que no puede encontrarlo
En este ejemplo, JavaScript comienza buscando a dentro del ámbito local, dentro de la función multiplier. Encuentra el valor de inmediato y pasa a b. No puede encontrar el valor de b en el ámbito local, por lo que pasa al ámbito externo. Aquí encuentra b que es 10. Por lo tanto, a * b se convierte en 5 * 10 y luego en 50.
Todo este fragmento de código podría estar dentro de otra función, y aún dentro de otra función. Si b no se encuentra aquí, JavaScript seguiría buscando b fuera de la función, capa tras capa.
Ten en cuenta que a = 7 no afecta a los cálculos. El valor de a se encontró internamente, por lo que el a externo no tuvo ningún efecto.
Este mecanismo se llama ámbito léxico. El ámbito de cualquier componente se determina por su ubicación en el código. Y los bloques anidados tienen acceso a sus ámbitos externos.
Cierre
La mayoría de los lenguajes de programación tienen algo similar al ámbito o entorno, y este mecanismo permite la existencia de cierres.
Un cierre es una combinación de una función y el entorno en el que se declaró. En otras palabras, es solo un nuevo nombre para una función que recuerda las cosas externas que utiliza.
Recordemos cómo se crean y utilizan las funciones:
La función f es bastante inútil, siempre devuelve 0. Todo este conjunto consta de dos partes:
- Constante
- La función en sí
Es importante recordar que estos dos componentes son independientes. El primero es una constante con el nombre f. Su valor podría ser un número o una cadena, pero aquí es una función.
Cuando llamamos a esta función, se ve así:
Volviendo a los cierres, consideremos el siguiente código:
La función createPrint crea la constante name y luego la función con el nombre printName. Ambas funciones y constantes creadas son locales, solo están disponibles dentro de createPrint.
La función printName no tiene componentes locales. Pero tiene acceso a su propio ámbito, es decir, al ámbito externo donde se definió la constante name.
Luego, la función createPrint devuelve la función printName. Recuerda que las definiciones de funciones son solo descripciones de funciones en ejecución, simplemente fragmentos de información, como números o cadenas. Por lo tanto, podemos devolver la definición de una función de la misma manera que devolvemos un número.
En el ámbito externo, creamos la constante myPrint y le asignamos el valor que devuelve la llamada a la función createPrint(). Esta llamada devuelve una función, por lo que ahora myPrint es una función. Llámala y se imprimirá King.
Aquí hay algo extraño: esta constante name se creó dentro de la función createPrint. La función se llamó y se ejecutó. Como sabemos, cuando una función termina su trabajo, ya no existe.
Esta caja mágica desaparece con todas sus partes internas, pero devuelve otra función que ya recuerda la constante name. Por lo tanto, cuando llamamos a myPrint(), imprime King - el valor recordado. Al mismo tiempo, ya no existe el ámbito donde definimos este valor.
La función que devolvimos de createPrint es un cierre. En otras palabras, es una combinación de una función y el entorno en el que se definió. La función cierra en sí misma cierta información del ámbito.
Cuando se usan de manera inteligente, los cierres pueden hacer que el código sea más agradable, más limpio y más fácil de leer. Incluso la idea de devolver funciones de la misma manera que se pueden devolver números o cadenas proporciona más posibilidades y flexibilidad.
Notarás cuánto se utilizan estas ideas en la programación. Exploraremos su potencial en los próximos cursos.
Completado
0 / 16