Saltar al contenido principal
03Funciones

Scope (Ámbito)

Clase 6 de 77 min de lectura

¿Qué es el Scope?#

Creas una variable, intentas usarla unas líneas más abajo y JavaScript te dice que no existe. No es un fallo del lenguaje: es el scope (ámbito), el contexto en el que los valores y las expresiones son «visibles» y se pueden usar.

La regla es sencilla: si una variable no está en el scope actual, no está disponible.

Además, los scopes se organizan en una jerarquía, unos dentro de otros. Los scopes hijos tienen acceso a los de sus padres, pero no al revés. Piensa en una casa: desde tu habitación puedes usar lo que hay en el pasillo, pero desde el pasillo nadie ve lo que guardas dentro de tu habitación.

¿Y quién crea esas habitaciones? Las funciones. Una función sirve como un cierre en JavaScript y, por lo tanto, crea un ámbito: una variable definida dentro de una función no se puede usar desde fuera ni desde otras funciones.

Veamos un ejemplo. Fíjate en dónde se declara cada variable y en las dos últimas líneas:

let nombre = 'Ana' // Variable globalfunction saludar() {  let apellido = 'García' // Variable local  console.log(nombre + ' ' + apellido) // Puede acceder a ambas}saludar() // -> "Ana García"console.log(nombre) // ✅ "Ana"console.log(apellido) // ❌ ReferenceError: apellido is not defined

Para que lo veas más claro, vamos a dibujarlo. Cada scope es una caja, y así ves en cuál vive cada variable.

Diagrama del Scope

Scope global
let nombre = 'Ana' // accesible en todo el código
Scope de función · saludar()
let apellido = 'García' // solo aquí dentro
console.log(nombre + apellido)
nombre → variable global (accesible)
apellido → variable local
La variable global es accesible en todas partes; la local solo dentro de su función.

Y de vuelta en el scope global:

Scope global
console.log(nombre) // funciona
console.log(apellido) // Error: no existe aquí

A la variable nombre podemos acceder tanto dentro como fuera de la función, porque está en el scope global.

En cambio, apellido se ha creado dentro de saludar, así que fuera de ella no existe. Decimos que está en el scope de la función saludar y que, por lo tanto, es local.

Cadena de ámbitos (Scope Chain)#

El ámbito global es el que tenemos en la raíz de nuestro código. A partir de ahí podemos crear un ámbito más localizado. Dentro, otro nuevo... y así sucesivamente, como muñecas rusas.

Lo que debes tener en cuenta es que los ámbitos inferiores pueden acceder a los superiores, pero no al revés. En este ejemplo hay tres niveles; mira qué puede ver cada uno:

let global = 'Soy global'function externa() {  let externa_var = 'Soy de la función externa'  function interna() {    let interna_var = 'Soy de la función interna'    // Puede acceder a todas:    console.log(interna_var) // -> "Soy de la función interna"    console.log(externa_var) // -> "Soy de la función externa"    console.log(global) // -> "Soy global"  }  // Aquí solo puedes acceder a "externa_var" y "global"  interna()  // console.log(interna_var) // ❌ Error: no puede acceder}// Aquí solo puedes acceder a la variable "global"externa()

Cuando interna necesita una variable, JavaScript la busca primero en su propio scope. Si no la encuentra, sube al scope del padre, y así hasta llegar al global. Ese recorrido es la cadena de ámbitos.

Diagrama de la Cadena de Scope

Infografía
Cómo busca JavaScript una variable
5.Desde externa pedimos interna_var. La búsqueda solo sube, nunca baja: no la encuentra y lanza un ReferenceError.
Paso 5 de 5

Prioridad de los scopes#

Vale, pero ¿y si hay variables con el mismo nombre en varios scopes? Gana la que esté más cerca. La prioridad es la siguiente:

  1. Scope local (función actual)
  2. Scope de función padre
  3. Scope global

Aquí hay tres variables name, una en cada nivel. Cada console.log muestra la de su propio scope:

let name = 'Global'function external() {  let name = 'External'  function internal() {    let name = 'Internal'    console.log(name) // -> "Internal" - prioridad local  }  internal()  console.log(name) // -> "External" - prioridad local}external()console.log(name) // -> "Global" - scope global

Como ves, no hay ningún problema en crear una variable o función con el mismo nombre que otra que ya existe en un scope superior. La de dentro simplemente tapa a la de fuera, sin modificarla.

Eso sí, no puedes hacerlo si estás en el mismo scope:

let name = 'Global'let name = 'Global' // ❌ SyntaxError: Identifier 'name' has already been declared

Tipos de Scope#

1. Scope Global

Aquí viven las variables y funciones declaradas en el nivel más alto del código. Cualquier función puede leerlas... y también modificarlas:

let colorFavorito = 'azul' // Scope globalfunction mostrarColor() {  console.log(colorFavorito) // Puede acceder}function cambiarColor() {  colorFavorito = 'rojo' // Puede modificar}mostrarColor() // -> "azul"cambiarColor()mostrarColor() // -> "rojo"

2. Scope de Función

Las variables declaradas dentro de una función solo existen dentro de ella:

function calcular() {  let resultado = 10 * 5 // Solo existe dentro de esta función  return resultado}console.log(calcular()) // ✅ 50// console.log(resultado) // ❌ Error: resultado is not defined

3. Scope de Bloque (con let y const)

Las funciones no son las únicas que crean un scope. También lo hace cualquier bloque entre llaves {}: un if, un for, un while... Compara lo que pasa con let y con var:

if (true) {  let dentroDelBloque = 'Solo aquí'  var fueraDelBloque = 'Disponible fuera'  console.log(dentroDelBloque) // ✅ Funciona}// console.log(dentroDelBloque) // ❌ Errorconsole.log(fueraDelBloque) // ✅ "Disponible fuera"

Resumiendo el ámbito (scope)#

El scope determina desde dónde puedes acceder a cada variable y a cada función. Y lejos de ser una limitación, juega a tu favor:

  • Encapsulación de datos.
  • Prevención de conflictos de nombres.
  • Organización del código.
  • Seguridad y privacidad.

En resumen

  • El scope decide dónde es visible cada variable: si no está en el scope actual, no existe para ese código.
  • Los scopes forman una jerarquía: los hijos acceden a los padres, pero no al revés.
  • JavaScript busca cada variable desde el scope local hacia el global, y con nombres repetidos gana la más cercana.
  • Hay scope global, de función y de bloque: let y const respetan el de bloque; var, solo el de función.