Cierres de funciones de JavaScript


Tabla de contenido

    Mostrar tabla de contenidos


Las variables de JavaScript pueden pertenecer al directorio local o Ámbito global.

Las variables globales se pueden convertir en locales (privadas) con cierres.


Variables globales

Una función puede acceder a todas las variables definidas dentro de la función, así:

Ejemplo

function myFunction() {
    let a = 4;
    return a * a;
}

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>A function can access variables defined inside the function:</p>

<p id="demo"></p>

<script>
myFunction();

function myFunction() {
  let a = 4;
  document.getElementById("demo").innerHTML = a * a;
}
</script>

</body>
</html>

Pero una función también puede acceder a variables definidas fuera de la función, como esta:

Ejemplo

let a = 4;
function myFunction() {
    return a * a;
}

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>A function can access variables defined outside the function:</p>

<p id="demo"></p>

<script>
let a = 4;
myFunction();

function myFunction() {
  document.getElementById("demo").innerHTML = a * a;
} 
</script>

</body>
</html>

En el último ejemplo, a es un global variable.

En una página web, las variables globales pertenecen a la página.

Las variables globales pueden ser utilizadas (y modificadas) por todos los demás scripts de la página.

En el primer ejemplo, a es un local variable.

Una variable local sólo se puede utilizar dentro de la función donde está definida. Él está oculto de otras funciones y otros códigos de secuencias de comandos.

Global y las variables locales con el mismo nombre son diferentes variables. Modificar uno, no modifica el otro.

Nota

Variables creadas sin una palabra clave de declaración (var, let, o const) son siempre globales, incluso si se crean dentro de una función.

Ejemplo

function myFunction() {
  a = 4;
}

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Functions</h2>
<p>Variables created without a declaration keyword (var, let, or const) are always global,
even if they are created inside a function.:</p>

<p id="demo"></p>

<script>
myFunction();
document.getElementById("demo").innerHTML = a * a;

function myFunction() {
  a = 4;
} 
</script>

</body>
</html>


Vida útil variable

Las variables globales viven hasta que se descarta la página, como cuando navegas a otra página o cerrar la ventana.

Local Las variables tienen vidas cortas. Se crean cuando la función es invocado y eliminado cuando finaliza la función.


Un contradilema

Supongamos que desea utilizar una variable para contar algo y desea que esto contador esté disponible para todas las funciones.

Podrías usar una variable global y una función para aumentar el contador:

Ejemplo

 // Initiate counter
let counter = 0;
// Function to increment 
  counter
function add() {
  counter += 1;
}
// Call add() 3 times
add();
add();
add();
// The counter should now be 3

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a global variable.</p>

<p id="demo"></p>

<script>
// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The counter should now be 3
document.getElementById("demo").innerHTML = "The counter is: " + counter;
</script>

</body>
</html>

Hay un problema con la solución anterior: cualquier código en la página puede cambiar el contador, sin llamando a agregar().

El contador debe ser local para la función add(), para evitar que cambie otro código. él:

Ejemplo

 // Initiate counter
let counter = 0;
// Function to increment 
  counter
function add() {
  let counter = 0; 
  
  counter += 1;
}
// 
  Call add() 3 times
add();
add();
add();
//The counter should 
  now be 3. But it is 0

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a local variable.</p>

<p id="demo"></p>

<script>
// Initiate counter
let counter = 0;

// Function to increment counter
function add() {
  let counter = 0; 
  counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The result is not 3 because you mix up the globaland local counter
document.getElementById("demo").innerHTML = "The counter is: " + counter;
</script>

</body>
</html>

No funcionó porque mostramos el contador global en lugar del local. encimera.

Podemos eliminar el contador global y acceder al contador local dejando que el función devolverlo:

Ejemplo

 // Function to increment 
  counter
function add() {
  let counter = 0; 
  
  counter += 1;
  return counter;
}
// 
  Call add() 3 times
add();
add();
add();
//The counter should 
  now be 3. But it is 1.

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Closures</h2>
<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
// Function to increment counter
function add() {
  let counter = 0;
  counter += 1;
  return counter;
}
// Trying to increment the counter
function myFunction(){
  document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

No funcionó porque reiniciamos el contador local cada vez que llamamos al función.

Una función interna de JavaScript puede resolver esto.


Funciones anidadas de JavaScript

Todas las funciones tienen acceso al ámbito global.

De hecho, en JavaScript, todas las funciones tienen acceso al alcance "por encima" de ellas.

JavaScript admite funciones anidadas. Las funciones anidadas tienen acceso a la alcance "por encima" de ellos.

En este ejemplo, la función interna plus() tiene acceso a la variable counter en la función principal:

Ejemplo

function add() {
    let counter = 0;
    function plus() {counter += 1;}
  plus();   
 
  return counter; 
}

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Function Closures</h2>
<p>Counting with a local variable.</p>

<p id="demo">0</p>

<script>
document.getElementById("demo").innerHTML = add();
function add() {
  let counter = 0;
  function plus() {counter += 1;}
  plus();  
  return counter; 
}
</script>

</body>
</html>

Esto podría haber resuelto el dilema del contador, si pudiéramos alcanzar el plus() funcionar desde el exterior.

También necesitamos encontrar una manera de ejecutar counter=0 solo una vez.

Necesitamos un cierre.


Cierres de JavaScript

¿Recuerdas las funciones de autoinvocación? ¿Qué hace esta función?

Ejemplo

const add = (function () {
  let counter = 0;
  return function () {counter += 1; return counter}
})();
add();
add();
add();

// the counter is now 3

Pruébelo usted mismo →

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Closures</h2>

<p>Counting with a local variable.</p>

<button type="button" onclick="myFunction()">Count!</button>

<p id="demo">0</p>

<script>
const add = (function () {
  let counter = 0;
  return function () {counter += 1; return counter;}
})();

function myFunction(){
  document.getElementById("demo").innerHTML = add();
}
</script>

</body>
</html>

Ejemplo explicado

La variable add se asigna al valor de retorno de un autoinvocador. función.

La función de autoinvocación solo se ejecuta una vez. Pone el contador a cero (0), y devuelve una expresión de función.

De esta manera agregar se convierte en una función. Lo "maravilloso" es que puede acceder el contador en el ámbito principal.

Esto se denomina cierre de JavaScript. Hace posible para que una función tenga variables "privadas".

El contador está protegido por el alcance de la función anónima, y solo se puede cambiar usando la función agregar.

Un cierre es una función que tiene acceso al ámbito principal, incluso después de que la función principal se haya cerrado.