Scope and Closures in JavaScript

Scope and Closures in JavaScript

Introduction

In the world of JavaScript, understanding the concepts of scope and closures is fundamental for writing efficient code and avoiding common mistakes. In this article, we will explore these concepts in depth and see how they apply in practical situations.

Scope in JavaScript

Scope in JavaScript refers to the current execution context. It determines the accessibility of variables and functions in different parts of the code.

Scope Global

Variables declared outside of any function have global scope and can be accessed from any part of the code.

Example:

let globalVar = 'Soy global';

function mostrarGlobal() {
  console.log(globalVar); // Puede acceder a globalVar
}

mostrarGlobal(); // Imprime: Soy global

Local Scope

Variables declared inside a function have local scope and are only accessible within that function.

Example:

function funcionLocal() {
  let localVar = 'Soy local';
  console.log(localVar); // Puede acceder a localVar
}

funcionLocal(); // Imprime: Soy local
console.log(localVar); // Error: localVar is not defined

Block Scope

Introduced in ES6, variables declared with let and const have block scope, which means they are only accessible within the block in which they are declared.

Example:

if (true) {
  let bloqueVar = 'Soy de bloque';
  console.log(bloqueVar); // Imprime: Soy de bloque
}

console.log(bloqueVar); // Error: bloqueVar is not defined

Closures in JavaScript

What is a Closure?

A closure is a function that has access to variables in its outer scope, even after the outer function has returned.

Example:

function crearContador() {
  let count = 0;
  return function () {
    count++;
    return count;
  };
}

const contador = crearContador();
console.log(contador()); // 1
console.log(contador()); // 2
console.log(contador()); // 3

In this example, contador is a closure that ‘remembers’ the value of count, even after crearContador has finished executing.

Practical Uses of Closures

  1. Encapsulation and data privacy:
function crearBanco() {
  let saldo = 0;
  return {
    depositar: function (cantidad) {
      saldo += cantidad;
      return saldo;
    },
    retirar: function (cantidad) {
      if (cantidad <= saldo) {
        saldo -= cantidad;
        return saldo;
      } else {
        return 'Fondos insuficientes';
      }
    },
    consultarSaldo: function () {
      return saldo;
    },
  };
}

const miCuenta = crearBanco();
console.log(miCuenta.depositar(100)); // 100
console.log(miCuenta.retirar(30)); // 70
console.log(miCuenta.consultarSaldo()); // 70
  1. Creation of factory functions:
function crearSaludo(saludo) {
  return function (nombre) {
    return `${saludo}, ${nombre}!`;
  };
}

const saludarFormal = crearSaludo('Buenas tardes');
const saludarInformal = crearSaludo('Hola');

console.log(saludarFormal('María')); // Buenas tardes, María!
console.log(saludarInformal('Juan')); // Hola, Juan!

Conclusion

Understanding scope and closures in JavaScript is essential for writing cleaner, more efficient, and safer code. Scope helps us organize our variables and functions, while closures allow us to create more powerful and flexible functions, with access to private data. Mastering these concepts will help you become a better JavaScript developer and solve problems more effectively.