Alcance de las variables globales y locales

En este artículo, obtendrás información sobre el alcance y cómo funciona en JavaScript.

El alcance es un concepto fundamental en JavaScript y en otros lenguajes de programación que define el contexto en el que se accede a las variables y se usan. Se vuelve más útil y aplicable a tu código a medida que continúes aprendiendo JavaScript y trabajando más con variables.

El permiso puede ayudarte a hacer lo siguiente:

  • Usa la memoria de manera más eficiente: El permiso permite cargar variables solo cuando es necesario. Si una variable está fuera del alcance, no es necesario que esté disponible para el código que se está ejecutando actualmente.
  • Encuentra y corrige errores con mayor facilidad: Aislar variables con permiso local facilita la solución de errores en tu código porque, a diferencia de las variables globales, puedes confiar en que el código de un permiso externo no puede manipular variables de alcance local.
  • Crea pequeños bloques de código reutilizable: Por ejemplo, puedes escribir una función pura que no se base en un alcance externo. Puedes mover fácilmente una función de este tipo a otro lugar con cambios mínimos.

¿Qué es el alcance?

El alcance de una variable determina en qué parte del código se puede usar una variable.

JavaScript define variables de alcance local o global:

  • Las variables con alcance global están disponibles en todos los demás alcances del código JavaScript.
  • Las variables con alcance local solo están disponibles dentro de un contexto local específico y se crean a partir de palabras clave, como var, let y const. Si usas las palabras clave var, let o const para crear una variable dentro de una función, esa variable tiene alcance local.

En las secciones posteriores de este artículo, se analiza el alcance léxico y el bloque:

  • Las variables de alcance de bloque están disponibles a nivel local para un bloque según lo determinado por la ubicación de las llaves en la que se define la sentencia de bloque. Solo las variables declaradas con las palabras clave let o const tienen alcance de bloque.
  • El alcance léxico usa la ubicación donde se declara una variable en el código fuente para determinar dónde está disponible. Se usan cierres para otorgar a una función cerrada acceso a variables a las que se hace referencia en el alcance externo, conocido como entorno léxico.

Cuando se accede a una variable dentro de su alcance, JavaScript muestra su valor asignado o produce un error.

Para declarar una variable, haz lo siguiente:

  • Usa las palabras clave var, const o let para declarar variables de alcance local o global.
  • Usa las palabras clave const o let para declarar variables de alcance de bloque.

Cuando declaras una variable var en una función, la declaración hace que la variable esté disponible para la función de cierre más cercana. No puedes usar la palabra clave var para declarar variables con alcance de bloque.

Ejemplos de alcance

En este ejemplo, se muestra el alcance global porque la variable greeting se declara fuera de cualquier función o bloque, lo que permite que su valor esté disponible para todo el código del documento actual:

const greeting = 'hello';
console.log(greeting); // 'hello'

En el ejemplo de alcance global, a la variable greeting se le asigna un valor hello.

En este ejemplo, se muestra el alcance local porque declara la variable greeting con la palabra clave let dentro de una función. La variable greeting es de alcance local y no está disponible fuera de la función.

function greet() {
  let greeting = 'Hello World!';
  console.log(greeting);
}

En este ejemplo, se muestra el alcance del bloque porque declara la variable greeting dentro de un bloque para que solo se pueda acceder a la variable dentro de las llaves:

if (true) {
   const greeting = 'hello';
}

console.log(greeting); // ReferenceError: greeting is not defined

Ten en cuenta que, cuando la función console.log intenta generar el valor de la variable greeting, JavaScript muestra un mensaje de error ReferenceError en lugar del mensaje hello esperado. ¿Por qué?

Se muestra un error porque la variable greeting tiene alcance de bloque y el bloque más cercano es parte de la sentencia condicional if. No puedes acceder a las variables let y const que declaras dentro de un bloque desde fuera del bloque. Por lo tanto, solo puedes acceder a la variable greeting entre llaves, que especifica el alcance del bloque.

En este ejemplo, se corrige el error porque mueve el método console.log(message) entre las llaves. El código actualizado reubica el método console.log(message) dentro del bloque.

if (true) {
   const greeting = 'hello';
   console.log(greeting);
}

Tipos de alcances

Alcance global

Puedes acceder a las variables con alcance global desde cualquier parte del programa.

Considera un archivo HTML que importa dos archivos JavaScript: file-1.js y file-2.js:

<script src="file-1.js"></script>
<script src="file-2.js"></script>

En este ejemplo, la variable globalMessage tiene un alcance global y está escrita fuera de una función. Durante la ejecución, puedes acceder al valor de la variable globalMessage desde cualquier parte del programa de JavaScript.

Puedes ver el contenido de los archivos file-1.js y file-2.js en este fragmento de código. Observa la disponibilidad de la variable globalMessage en ambos archivos.

// file-1.js
function hello() {
    var localMessage = 'Hello!';
}

var globalMessage = 'Hey there!';

// file-2.js
console.log(localMessage); // localMessage is not defined
console.log(globalMessage); // Hey there!

Hay otro tipo de alcance que no se discute mucho en este artículo. Si creas una variable dentro de un módulo de JavaScript, pero fuera de una función o un bloque, no tiene un alcance global, sino un alcance del módulo. Las variables con alcance de módulo están disponibles en cualquier lugar del módulo actual, pero no en otros archivos o módulos. Si quieres que una variable específica del módulo esté disponible para otros archivos, debes exportarla desde el módulo en el que se crea y, luego, import desde el módulo que necesita acceder a la variable.

Alcance local y alcance de la función

Cuando creas variables en una función de JavaScript con las palabras clave var, let o const, las variables son locales para la función, por lo que solo puedes acceder a ellas desde dentro de ella. Las variables locales se crean cuando se inicia una función y se borran cuando finaliza su ejecución.

En este ejemplo, se declara la variable total en la función addNumbers(). Solo puedes acceder a las variables a, b, y total dentro de la función addNumbers().

function addNumbers(a, b) {
    const total = a + b;
}

addNumbers(3, 4);

Puedes usar las palabras clave let y const para nombrar las variables. Cuando usas la palabra clave let, JavaScript puede actualizar la variable. Sin embargo, con la palabra clave const, la variable permanece constante.

var variable1 = 'Declared with var';
var variable1 = 'Redeclared with var';
variable1; // Redeclared with var

let variable2 = 'Declared with let. Cannot be redeclared.';
variable2 = 'let cannot be redeclared, but can be updated';
variable2; // let cannot be redeclared, but can be updated

const variable3 = 'Declared with const. Cannot be redeclared or updated';
variable3; // Declared with const. Cannot be redeclared or updated

Alcance del bloque

Los bloques se usan para agrupar una sola declaración o un conjunto de declaraciones. Puedes usar las palabras clave const o let para declarar una variable local con alcance de bloque. Ten en cuenta que no puedes usar la palabra clave var para declarar variables con alcance de bloque.

Por ejemplo, en este bloque, el alcance de la variable name y su valor "Elizabeth" se encuentran dentro de las llaves. Las variables dentro del alcance de un bloque no están disponibles fuera del bloque.

{
    const name = "Elizabeth";
}

Puedes usar variables de alcance de bloque dentro de las sentencias if, for o while.

Toma nota de los dos bucles for dentro de este fragmento de código. Un bucle for usa la palabra clave var para declarar la variable de inicializador, que aumenta a través de los números 0, 1 y 2. El otro bucle for usa la palabra clave let para declarar la variable de inicializador.

for (var i = 0; i < 2; i++) {
    // ...
}

console.log(i); // 2

for (let j = 0; j < 2; j++) {
    // ...
}

console.log(j); // The j variable isn't defined.

En el ejemplo de código anterior, puedes observar que la variable i del primer bucle for se filtró fuera del bucle for y aún retiene un valor 2 porque la palabra clave var no usa el alcance de bloque. El problema se soluciona en el segundo bucle for, en el que la variable j declarada con la palabra clave let se limita al bloque del bucle for y no existe después de que finaliza el bucle for.

Reutiliza el nombre de una variable en un alcance diferente

El permiso puede aislar una variable dentro de una función, incluso cuando reutilizas el mismo nombre de variable en otra parte de un alcance diferente.

En este ejemplo, se muestra cómo el uso del alcance te permite reutilizar el mismo nombre de variable en diferentes funciones:

function listOne() {
    let listItems = 10;
    console.log(listItems); // 10
}

function listTwo() {
   let listItems = 20;
   console.log(listItems); // 20
}

listOne();
listTwo();

A las variables listItems de las funciones listOne() y listTwo() se les asignan los valores esperados y, por lo tanto, no entran en conflicto.

Cierres y alcance léxico

Los cierres hacen referencia a una función delimitada en la que una función interna puede acceder al alcance de la función externa, que también se conoce como entorno léxico. Por lo tanto, en JavaScript, se usan cierres para permitir que las funciones hagan referencia al entorno léxico externo, lo que permite que el código dentro de una función haga referencia a variables declaradas fuera de la función. De hecho, puedes codificar una cadena de referencias a entornos léxicos externos para que una función llame a una función, que, a su vez, la llame otra función.

En este ejemplo, el código forma un cierre con el entorno léxico que se crea cuando se invoca la función outer(), la cual se cierra sobre la variable hello. Por lo tanto, se usa la variable hello dentro de la función de devolución de llamada setTimeout.

function outer() {
    const hello = 'world';

    setTimeout(function () {
        console.log('Within the closure!', hello)
    }, 100);
}

outer();

Con el alcance léxico, el alcance se determina durante la compilación del código fuente, no durante el tiempo de ejecución. Para obtener más información sobre el entorno léxico, consulta Alcance léxico y cierre.

Módulos

Los módulos de JavaScript ayudan a organizar el código JavaScript. Si se usan correctamente, proporcionan una estructura eficaz para tu base de código y ayudan a reutilizarlo. En lugar de usar variables globales para compartir variables entre diferentes archivos, los módulos de JavaScript proporcionan una técnica para exportar e import variables.

// hello.js file
function hello() {
  return 'Hello world!';
}

export { hello };

// app.js file
import { hello } from './hello.js';

console.log(hello()); // Hello world!

Demostración del visualizador de alcance

El alcance es un concepto fundamental que todo desarrollador de JavaScript debe comprender. Para comprender mejor el sistema de permisos, puedes intentar escribir tu propio código con el Visualizador de permisos de JS. La demostración usa coloración en el código para ayudarte a visualizar los alcances de JavaScript.

Conclusión

En este artículo, se presentan diferentes tipos de alcance. El alcance de JavaScript es uno de los conceptos más avanzados dentro del desarrollo web, por lo que es genial que hayas leído este contenido y te hayas tomado el tiempo para comprenderlo.

El permiso no es una función para el usuario. Solo afecta al desarrollador web que escribe el código, pero conocer cómo funciona el alcance puede ayudarte a corregir errores cuando surgen.