Funciones anónimas y clausuras

Formas de crear funciones anónimas y ejecutarlas


Las funciones anónimas (o funciones lambda) son un tipo de funciones que se declaran sin definir un nombre de función, alojándolas en el interior de una variable y haciendo referencia a dicha variable cada vez que queramos utilizarla. Vimos este concepto en el apartado de funciones por expresión del artículo anterior ¿Qué son las funciones?.

Sin saberlo, creamos de forma intuitiva una función anónima:

// Función anónima "saludo"
const saludo = function () {
  return "Hola";
};

saludo(); // 'Hola'
saludo;   // ƒ () { return 'Hola'; }

Observa que, tras definir la función, hace dos acciones:

  • 1️⃣ Ejecutamos la variable saludo, que como contiene una función, se ejecuta la función
  • 2️⃣ Mostramos el valor de la variable saludo (no indicamos paréntesis, no ejecutamos)

Funciones autoejecutables

Ahora que tenemos claro el concepto de función anónima, vamos a ver un caso donde puede ser útil. Pueden existir casos en los que necesites crear una función y ejecutarla inmediatamente, sabiendo que no la vas a volver a necesitar. Este tipo de funciones muchas veces también se llama IIFE (Función por expresión invocada inmediatamente).

Esto se puede resolver con lo que se llama una función autoejecutables. Básicamente, sólo tenemos que envolver entre paréntesis la función anónima en cuestión (no necesitamos que tenga nombre, puesto que no la vamos a guardar) y luego, ejecutarla:

(function () {
  console.log("Hola!!");
})();

De hecho, también podemos utilizar parámetros en dichas funciones autoejecutables. Observa que sólo hay que pasar los parámetros deseados al final de la función autoejecutable:

(function (name) {
  console.log(`¡Hola, ${name}!`);
})("Manz");

Ten en cuenta que, si la función autoejecutable devuelve algún valor con return, a diferencia de las funciones por expresión, en este caso lo que se almacena en la variable es el valor que devuelve la función autoejecutada:

const value = (function (name) {
  return `¡Hola, ${name}!`;
})("Manz");

value;        // '¡Hola, Manz!`
typeof value; // 'string'

¿Qué está ocurriendo aquí? Analicemos paso por paso:

  • 1️⃣ Se ejecuta la función autoejecutable contenida en paréntesis.
  • 2️⃣ La función toma el valor Manz como parámetro name.
  • 3️⃣ La función devuelve el valor ¡Hola, Manz! como resultado.
  • 4️⃣ La variable value almacena el valor devuelto por la función autoejecutada.

Clausuras

Las clausuras (o cierres) son un concepto relacionado con las funciones y los ámbitos que suele costar comprender cuando se empieza en Javascript. Es importante tener las bases de funciones claras hasta este punto, para poder entender las bases de una clausura.

A grandes rasgos, en Javascript, una clausura o cierre se define como una función que «encierra» variables en su propio ámbito (y que continúan existiendo aún habiendo terminado de ejecutar la función).

Por ejemplo, veamos el siguiente ejemplo:

const incr = (function () {
  let num = 0;
  return function () {
    num++;
    return num;
  };
})();

Analicemos primero lo que tenemos en este código, y luego analicemos lo que ocurre cuando ejecutamos la función:

  • 1️⃣ Tenemos una función anónima que es también una función autoejecutable.
  • 2️⃣ Adelántate, y observa que la función autoejecutable devuelve otra función diferente.
  • 3️⃣ Al ejecutar la función la primera vez (autoejecutable) devolvemos esa otra función que es la que se guarda en incr para futuras ejecuciones.

La «magia» de las clausuras es que en el interior de la función autoejecutable estamos creando una variable num que se guardará en el ámbito de dicha función autoejecutable, por lo tanto seguirá existiendo, inicialmente con el valor declarado: 0.

Por lo tanto, en la variable incr guardamos una función que además conoce el valor de una variable num, que sólo existe dentro de incr.

typeof incr; // 'function'
incr(); // 1
incr(); // 2
incr(); // 3

Si nos fijamos en la función que devolvemos, lo que hace es incrementar el valor de num y devolverlo. Como la variable incr es una clausura y mantiene la variable en su propio ámbito, veremos que a medida que ejecutamos incr(), los valores de num (que estamos devolviendo) conservan su valor y se van incrementando.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev