Introducción al alcance en JavaScript

El alcance define la vida útil y la visibilidad de una variable. Las variables no son visibles fuera del ámbito en el que se declaran.

JavaScript tiene alcance de módulo, alcance de función, alcance de bloque, alcance léxico y alcance global.

Alcance global

Las variables definidas fuera del alcance de cualquier función, bloque o módulo tienen alcance global. Se puede acceder a las variables de alcance global desde cualquier lugar de la aplicación.

Cuando se habilita un sistema de módulos, es más difícil crear variables globales, pero aún se puede hacerlo. Al definir una variable en HTML, fuera de cualquier función, se puede crear una variable global:

 let GLOBAL_DATA = { value : 1};  console.log(GLOBAL_DATA);

Cuando no hay un sistema de módulos en su lugar, es mucho más fácil crear variables globales. Una variable declarada fuera de cualquier función, en cualquier archivo, es una variable global.

Las variables globales están disponibles durante la vida útil de la aplicación.

Otra forma de crear una variable global es utilizar el windowobjeto global en cualquier lugar de la aplicación:

window.GLOBAL_DATA = { value: 1 };

En este punto, la GLOBAL_DATAvariable es visible en todas partes.

console.log(GLOBAL_DATA)

Como puedes imaginar, estas prácticas son malas prácticas.

Alcance del módulo

Antes de los módulos, una variable declarada fuera de cualquier función era una variable global. En los módulos, una variable declarada fuera de cualquier función está oculta y no está disponible para otros módulos a menos que se exporte explícitamente.

La exportación hace que una función u objeto esté disponible para otros módulos. En el siguiente ejemplo, exporto una función del sequence.jsarchivo del módulo:

// in sequence.js export { sequence, toList, take };

La importación hace que una función u objeto, de otros módulos, esté disponible para el módulo actual.

import { sequence, toList, toList } from "./sequence";

En cierto modo, podemos imaginar un módulo como una función autoejecutable que toma los datos de importación como entradas y devuelve los datos de exportación.

Alcance de la función

El alcance de la función significa que los parámetros y variables definidos en una función son visibles en todas partes dentro de la función, pero no son visibles fuera de la función.

Considere la siguiente función que se ejecuta automáticamente, llamada IIFE.

(function autoexecute() { let x = 1; })(); console.log(x); //Uncaught ReferenceError: x is not defined

IIFE significa Expresión de función invocada inmediatamente y es una función que se ejecuta inmediatamente después de su definición.

Las variables declaradas con varsolo tienen alcance de función. Aún más, las variables declaradas con varse elevan al tope de su alcance. De esta forma se puede acceder a ellos antes de ser declarados. Eche un vistazo al siguiente código:

function doSomething(){ console.log(x); var x = 1; } doSomething(); //undefined

Esto no pasa por let. Se letpuede acceder a una variable declarada con solo después de su definición.

function doSomething(){ console.log(x); let x = 1; } doSomething(); //Uncaught ReferenceError: x is not defined

Una variable declarada con varse puede volver a declarar varias veces en el mismo ámbito. El siguiente código está bien:

function doSomething(){ var x = 1 var x = 2; console.log(x); } doSomething();

Variables declaradas con leto constno pueden volver a declararse en el mismo ámbito:

function doSomething(){ let x = 1 let x = 2; } //Uncaught SyntaxError: Identifier 'x' has already been declared

Tal vez ni siquiera tengamos que preocuparnos por esto, ya que varha comenzado a quedar obsoleto.

Alcance del bloque

El alcance del bloque se define con llaves. Está separado por {y }.

Las variables declaradas con lety constpueden tener alcance de bloque. Solo se puede acceder a ellos en el bloque en el que están definidos.

Considere el siguiente código que enfatiza el letalcance del bloque:

let x = 1; { let x = 2; } console.log(x); //1

Por el contrario, la vardeclaración no tiene alcance de bloque:

var x = 1; { var x = 2; } console.log(x); //2

Otro problema común de no tener alcance de bloque es el uso de una operación asincrónica como setTimeout()en un bucle. El código de bucle fluido muestra el número 5 cinco veces.

(function run(){ for(var i=0; i<5; i++){ setTimeout(function logValue(){ console.log(i); //5 }, 100); } })();

La fordeclaración de bucle, con la letdeclaración, crea una nueva configuración regional variable para el alcance del bloque, para cada iteración. Se muestra el siguiente código de bucle 0 1 2 3 4 5.

(function run(){ for(let i=0; i<5; i++){ setTimeout(function log(){ console.log(i); //0 1 2 3 4 }, 100); } })();

Alcance léxico

El alcance léxico es la capacidad de la función interna para acceder al alcance externo en el que está definida.

Considere el siguiente código:

(function autorun(){ let x = 1; function log(){ console.log(x); }; function run(fn){ let x = 100; fn(); } run(log);//1 })();

La logfunción es un cierre. Hace referencia a la xvariable de su función padre autorun(), no a la de la run()función.

La función de cierre tiene acceso al ámbito en el que se creó, no al ámbito en el que se ejecutó.

The local function scope of autorun() is the lexical scope of the log() function.

Scope chain

Every scope has a link to the parent scope. When a variable is used, JavaScript looks down the scope chain until it either finds the requested variable or until it reaches the global scope, which is the end of the scope chain.

Look at the next example:

let x0 = 0; (function autorun1(){ let x1 = 1; (function autorun2(){ let x2 = 2; (function autorun3(){ let x3 = 3; console.log(x0 + " " + x1 + " " + x2 + " " + x3);//0 1 2 3 })(); })(); })();

The autorun3() inner function has access to the local x3 variable. It has also access to the x1 and x2 variables from the outer functions and the x0 global variable.

If it cannot find the variable, it will return an error in strict mode.

"use strict"; x = 1; console.log(x) //Uncaught ReferenceError: x is not defined

In non-strict mode, referred to as “sloppy mode”, it will do a bad thing and create a global variable.

x = 1; console.log(x); //1

Conclusion

Variables defined in global scope are available everywhere in the application.

In a module, a variable declared outside any function is hidden and not available to other modules unless it is explicitly exported.

Function scope means that parameters and variables defined in a function are visible everywhere within the function

Variables declared with let and const have block scope. var doesn’t have block scope.

Discover Functional JavaScript was named one of thebest new Functional Programming books by BookAuthority!

For more on applying functional programming techniques in React take a look atFunctional React.

Learn functional React, in a project-based way, with Functional Architecture with React and Redux.

Follow on Twitter