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 otros lenguajes de programación que define el contexto en el que se accede a las variables y se usan. A medida que continúas aprendiendo JavaScript y trabajando más con variables, se vuelve más útil y aplicable a tu código.

El alcance puede ayudarte a lograr lo siguiente:

  • Usa la memoria de manera más eficiente: El permiso proporciona la capacidad de cargar variables solo cuando es necesario. Si una variable está fuera del alcance, no es necesario que la pongas a disposición del código que se está ejecutando actualmente.
  • Encuentra y corrige errores con mayor facilidad: Aislar variables con alcance 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 desde un alcance externo no puede manipular variables con alcance local.
  • Crea pequeños bloques de código reutilizable: Por ejemplo, puedes escribir una función pura que no dependa de un alcance externo. Puedes mover fácilmente esa función a otro lugar con cambios mínimos.

¿Qué es el alcance?

El alcance de una variable determina desde qué parte del código puedes usar una variable.

JavaScript define variables de alcance global o local:

  • Las variables con alcance global están disponibles desde todos los demás alcances en el código de 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 del bloque están disponibles de forma 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. Usa cierres para otorgar a una función delimitada acceso a las 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 delimitante 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 hace 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 una variable 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 entre 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, ya que mueve el método console.log(message) dentro de 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 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 se escribe fuera de una función. Durante la ejecución y 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 analiza demasiado 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 alcance global, sino alcance del módulo. Las variables con alcance del módulo están disponibles en cualquier lugar del módulo actual, pero no lo están en otros archivos o módulos. Para hacer que una variable con alcance de módulo esté disponible para otros archivos, debes exportarla desde el módulo en el que se creó 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 de manera efectiva 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 asignar nombres a 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

Bloquear el alcance

Los bloques se usan para agrupar una sola sentencia o un conjunto de sentencias. 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 incluyen entre 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 en 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 conserva un valor 2 porque la palabra clave var no usa el alcance de bloque. El problema se corrigió 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.

Reutilización de un nombre de variable en un alcance diferente

El alcance puede aislar una variable dentro de una función, incluso cuando reutilizas el mismo nombre de variable en otro lugar 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 en las funciones listOne() y listTwo() se les asignan los valores esperados y, por lo tanto, no entran en conflicto entre sí.

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 exterior, que también se conoce como entorno léxico. Por lo tanto, en JavaScript, usas cierres para permitir que las funciones hagan referencia al entorno léxico externo, que permite que el código dentro de una función haga referencia a variables declaradas fuera de la función. De hecho, puedes programar una cadena de referencias a entornos léxicos externos para que una función llame a una función y, a su vez, otra función la llame.

En este ejemplo, el código forma un cierre con el entorno léxico que se crea cuando se invoca la función outer(), que se cierra sobre la variable hello. Por lo tanto, la variable hello se usa 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 en el tiempo de ejecución. Para obtener más información sobre el entorno léxico, consulta Alcance y cierre léxicos.

Módulos

Los módulos de JavaScript ayudan a organizar el código. Si se usan correctamente, proporcionan una estructura eficaz a 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 importar y import.

// 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 permisos

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 JS Scope Visualizer. En la demostración, se usan colores en el código para ayudarte a visualizar los alcances de JavaScript.

Conclusión

En este artículo, se presentan diferentes tipos de alcances. 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 comprender este tema.

El alcance 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 los errores que surjan.