Todo sobre funciones y ámbitos en JavaScript

En este artículo, cubriremos todos los conceptos básicos de las funciones JS, devoluciones de llamada, alcances, cierres en profundidad que lo ayudarán a:

  • comprender los diferentes tipos de declaración de funciones.
  • hacer un mejor uso de las funciones.
  • comprender cómo funcionan los diferentes ámbitos y la string de ámbitos en JS.
  • Aprenda acerca de los cierres y cómo usarlos.

Comprenderemos todos estos conceptos a través de los ejemplos y también comprenderemos sus implementaciones. Comencemos la discusión con la función Javascript.

Funciones: la función nos permite declarar y empaquetar un montón de código en un bloque para que podamos usar (y reutilizar) un bloque de código en nuestros programas. A veces, toman algunos valores como «parámetros» para realizar la operación y devuelven algún valor como resultado de la operación.

Ejemplo:

Javascript

function add(a, b) {
  
    // a and b are the parameters of this
    // function code to do the operation
    return a + b; // return statement
}
 
// Invoking the function and 2, 3
// are arguments here
add(2, 3);

Producción: 

5

Ciudadano de primera clase: si algún lenguaje de programación tiene la capacidad de tratar funciones como valores, pasarlas como argumentos y devolver una función de otra función, entonces se dice que el lenguaje de programación tiene funciones de primera clase y las funciones se llaman de primera clase. Ciudadanos en ese lenguaje de programación. Las funciones serán consideradas First-Class Citizen en JavaScript si las funciones:

  • almacenar funciones en una variable.
  • pasar una función como argumento a otra función.
  • devolver una función de otra función.

Expresiones de función: cuando una función se almacena dentro de una variable, se denomina expresión de función. Esto puede ser nombrado o anónimo. Si una función no tiene ningún nombre y se almacena en una variable, se conocería como una expresión de función anónima . De lo contrario, se conocería como una expresión de función con nombre. Consulte el artículo de expresión de la función de JavaScript para obtener más detalles.

Ejemplo:

Javascript

// Anonymous function expression
const add = function (a, b){
    return a + b;
}
 
// Named function expression
const subtractResult = function subtract(a, b){
    return a - b;
}
 
console.log(add(3, 2)); // 5
console.log(subtractResult(3, 2)); // 1

La salida será 5 y 1 respectivamente.

Devoluciones de llamada: almacenar una función en una variable hace que sea muy fácil pasar una función a otra función como argumento. Una función que toma otras funciones como argumentos o devuelve una función se conoce como función de orden superior . Una función que se pasa como argumento a otra función se conoce como función de devolución de llamada . En palabras simples, si queremos ejecutar una función justo después de la devolución de alguna otra función, se pueden usar las devoluciones de llamada. Consulte JavaScript | Artículo de devoluciones de llamada para más detalles.

Ejemplo:

Javascript

function showLength(name, callback) {
  callback(name);
}
 
// function expression `nameLength`
const nameLength = function (name) {
  console.log(`Given Name ${name} which
  is ${name.length} chars long`);
};
 
// Passing `nameLength` as a callback function
showLength("GeeksforGeek", nameLength);

Producción:

Given Name GeeksforGeek which is 12 characters long

Template Literal en ES6 proporciona nuevas funciones para crear una string que brinda más control sobre las strings dinámicas. Tradicionalmente, String se crea usando comillas simples (‘) o comillas dobles («). El literal de la plantilla se crea utilizando el carácter de acento grave (`) que permite declarar las expresiones incrustadas. En general, usamos la función de devolución de llamada en los métodos de array: forEach(), map(), filter(), reduce().

Alcance: Es una región del programa donde se puede acceder a una variable. En otras palabras, el alcance determina la accesibilidad/visibilidad de una variable. Dado que JavaScript parece un lenguaje de la familia C, es muy obvio pensar que el alcance en JavaScript es similar al de la mayoría de los lenguajes de programación de back-end como C, C++ o Java. Consulte la sección ¿Qué es el alcance variable en JavaScript? artículo para más detalles. Hay 3 tipos de ámbitos en JavaScript:

  • Ámbito global : las variables declaradas fuera de todas las funciones se conocen como variables globales y en el ámbito global. Las variables globales son accesibles en cualquier parte del programa.
  • Ámbito de la función : Las variables que se declaran dentro de una función se denominan variables locales y en el ámbito de la función. Las variables locales son accesibles desde cualquier lugar dentro de la función.  
  • Alcance del bloque: variable que se declara dentro de un bloque específico y no se puede acceder a ella fuera de ese bloque. Para acceder a las variables de ese bloque específico, necesitamos crear un objeto para él.

El código dentro de una función tiene acceso a:

  • los argumentos de la función.
  • variables locales declaradas dentro de la función.
  • variables declaradas en el alcance de su función principal.
  • variables globales.

Javascript

const name = "GeeksforGeeks";
 
function introduceMyself(greet) {
  const audience = "Everyone";
  function introduce() {
    console.log(`${greet} ${audience}, This is ${name} Learning!`);
  }
  introduce();
}
 
introduceMyself("Hello");

Producción:

Hello Everyone, This is GeeksforGeeks Learning!

Ámbito de bloque: Esto nos dice que cualquier variable declarada dentro de un bloque ({}) solo se puede acceder dentro de ese bloque.  

Ahora, ¿qué es un bloque ? un bloque {} se usa para agrupar declaraciones de JavaScript en 1 grupo para que pueda usarse en cualquier parte del programa donde solo se espera que se escriba 1 declaración.

El alcance del bloque está relacionado con las variables declaradas con `let` y `const` únicamente. Las variables declaradas con `var` no tienen alcance de bloque.

Ejemplo:

{
    let a = 3;
    var b = 2;
}

console.log(a); //Uncaught ReferenceError: a is not defined
console.log(b); // 2 as variables declared with `var` is  
functionally and globally scoped NOT block scoped

String de alcance: cada vez que nuestro código intenta acceder a una variable durante la llamada a la función, inicia la búsqueda desde las variables locales. Y si no se encuentra la variable, continuará buscando en su ámbito externo o en el ámbito de las funciones principales hasta que llegue al ámbito global y complete la búsqueda de la variable allí. La búsqueda de cualquier variable ocurre a lo largo de la string de ámbito o en diferentes ámbitos hasta que obtenemos la variable. Si la variable tampoco se encuentra en el ámbito global, se genera un error de referencia.  

Ejemplo:

Javascript

const name = "GeeksforGeeks";
 
function introduceMyself(greet) {
  const audience = "Everyone";
 
  function introduce() {
    console.log(`${greet} ${audience}, This is ${name} Learning`);
  }
 
  introduce();
}
 
introduceMyself("Hello");

Producción:

Hello Everyone, This is GeeksforGeeks Learning

En el ejemplo anterior, cuando el código intenta acceder a la variable `name` dentro de la función `introduce()`, no obtuvo la variable allí y trató de buscar en el alcance de su función principal (`presenteMyself()`). Y como no estaba allí, finalmente subió al ámbito global para acceder a la variable y obtuvo el valor de la variable `nombre`.

Sombreado de variables: si declaramos una variable con el mismo nombre que otra variable en la string de alcance, la variable con alcance local sombreará la variable en el alcance externo. Esto se conoce como sombreado variable . Consulte el artículo Sombreado de variables en JavaScript para obtener más detalles.

Ejemplo 1:

Javascript

let name = "Abhijit";
var sector = "Government";
 
{
  let name = "Souvik";
   
  // as `var` is NOT block scoped(globally s
  // coped here), it'll update the value
  var sector = "Private";
  console.log(name); //Souvik
  console.log(sector); //Private
}
 
console.log(name); //Abhijit
console.log(sector); //Private

Producción:

Souvik
Private
Abhijit
Private

Ejemplo 2:

Javascript

let name = "Abhijit";
var sector = "Government";
 
function showDetails() {
  let name = "Souvik";
 
  // `var` is functionally scoped here,
  // so it'll create new reference with
  // the given value for organization
  var sector = "Private";
  console.log(name); // Souvik
  console.log(sector); // Private
}
 
showDetails();
console.log(name); // Abhijit
console.log(sector); // Government

Explicación : en el caso del ejemplo 1, la variable `name` oculta la variable con el mismo nombre en el ámbito exterior dentro del bloque, ya que hemos usado `let` para declarar la variable. Pero, la variable `sector` también está actualizando el valor al mismo tiempo que hemos usado `var` para declararlo. Y como sabemos que `var` tiene un alcance funcional y global, la declaración con el mismo nombre (`sector`) dentro del bloque actualizará el valor en la misma referencia. Mientras que en el caso del ejemplo 2, la variable `sector` dentro de la función tiene un alcance de función y creará una nueva referencia que simplemente sombreará la variable con el mismo nombre declarada fuera.

Producción:

Souvik
Private
Abhijit
Government

Cierre: Es la capacidad de una función para recordar las variables y funciones que se declaran en su ámbito externo.

MDN define el cierre como – «La combinación de una función agrupada junto con referencias a su estado circundante o al entorno léxico «

Ahora, si estás pensando, ¿cuál es el entorno léxico ? El entorno local de la función junto con el entorno de su función principal forma un entorno léxico. Consulte el artículo Cierre en JavaScript para comprender este concepto.

Ejemplo:

Javascript

function closureDemo(){
    const  a = 3;
     
    return function (){
          console.log(a); 
    }
}
 
// Returns the definition of inner function
const innerFunction = closureDemo();
innerFunction(); // 3

La salida será 3.

En el ejemplo anterior, cuando se llama a la función `closureDemo()`, devolverá la función interna junto con su alcance léxico. Luego, cuando intentemos ejecutar la función devuelta, intentará registrar el valor de `a` y obtener el valor de la referencia de su ámbito léxico. Esto se llama cierre . Incluso después de la ejecución de la función externa, la función devuelta aún contiene la referencia del ámbito léxico.

ventajas:

  • Zurra
  • Memoización
  • Patrón de diseño del módulo

Desventajas:

  • El consumo excesivo de memoria puede conducir a la pérdida de memoria, ya que la función más interna contiene la referencia del ámbito léxico y las variables declaradas en su ámbito léxico no se recolectarán como basura incluso después de que se haya ejecutado la función externa.

Expresión de función invocada inmediatamente (IIFE): una expresión de función invocada inmediatamente o IIFE es una función que se llama inmediatamente una vez que se define. Consulte JavaScript | Expresiones de funciones inmediatamente invocadas (IIFE) para obtener más detalles.

Sintaxis:

(function task(){
    console.log("Currently writing a blog on JS functions");
})();

Básicamente, envolvemos una función entre paréntesis y luego agregamos un par de paréntesis al final para invocarla.

  • Pasar argumentos a IIFE: También podemos pasar argumentos a IIFE. El segundo par de paréntesis no solo se puede usar para invocar la función inmediatamente, sino que también se puede usar para pasar cualquier argumento al IIFE. 
(function showName(name){
   console.log(`Given name is ${name}`); // Given name is Souvik
})("Souvik");
  • IIFE y alcance privado: si podemos usar IIFE junto con el cierre, podemos crear un alcance privado y proteger algunas variables para que no se acceda a ellas desde el exterior. La misma idea se utiliza en los patrones de diseño de módulos para mantener las variables en privado.  

Ejemplo:

Javascript

// Module pattern
let greet = (function () {
  const name = "GeekforGeeks"; // Private variable
 
  return {
    introduce: function () {
      console.log(`Hello, This is ${name} Learning!`);
    },
  };
})();
 
console.log(greet.name); //undefined
 
// Hello, This is GeekforGeeks Learning!
greet.introduce();

IIFE ayuda a evitar el acceso a la variable ‘nombre’ aquí. Y el método `introduce()` del objeto devuelto conserva el alcance de su función principal (debido al cierre), obtuvimos una interfaz pública para interactuar con `name`.

Producción:

undefined
Hello, This is GeekforGeeks Learning!

Publicación traducida automáticamente

Artículo escrito por sjsouvik y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *