Tipos de función en JavaScript

En JavaScript podemos definir una función de dos formas diferentes. Aunque ambas formas sirven para definir bloques de código que se pueden ejecutar más tarde, la diferencia principal radica en cómo se crean y cómo las maneja el motor de JavaScript antes de ejecutar el código.

- Estas dos modalidades son:

FUNCIONES DECLARADAS (o clásicas)

Se definen usando la palabra clave function. El navegador las lee antes de ejecutar cualquier otra cosa. En consecuencia, se puede llamar a la función antes de la línea donde se escribió y funcionará perfectamente. (A este proceso se le conoce como hoisting.)

Sintaxis

function nombre([parameters...]) {
  ... instrucciones...
  [return valor;]
}

Ejemplo

let x = cuadrado(5);
// ¡Funciona! Aunque la instrucción esté arriba

function cuadrado(numero) {
  return numero * numero
}

FUNCIONES EXPRESADAS

En este caso, la función se crea y se asigna a una variable (como si fuera un valor). Es la base de las famosas Arrow Functions (funciones flecha).

Las funciones expresadas se comportan como cualquier otra variable. Si se intenta llamar antes de definirla, JavaScript lanzará un error porque la variable aún no ha sido inicializada.

Sintaxis

const variable = function nombre([parameters...]) {
  ... instrucciones...
  [return valor;]
}

Este tipo de funciones puede ser anónima, es decir, la función como tal, no tiene por qué tener un nombre. Cuando las funciones son anónimas se denominan también funciones lambda

Sintaxis (anónima)

const variable = function ([parameters...]) {
  ... instrucciones...
  [return valor;]
}

Ejemplo

let x = sqr(5);
// Nótese que se llaman por su nombre
// ❌ ¡Error! Cannot access 'sqr' before initialization

const sqr = function cuadrado(numero) {
  return numero * numero
}

Funciones expresadas

Utilizar funciones expresadas permite crear una función en el interior de una variable, lo que permitirá posteriormente ejecutar la variable (como si fuera una función).

const sqr = function (numero) { return numero * numero }
let radio = 2;
alert(sqr(radio)); // muestra 4

Las funciones expresadas son convenientes cuando se pasa una función como argumento a otra función.

// MOSTRAR EL AREA DE UN CIRCULO
const sqr = function (numero) { return numero * numero }

function areaCirculo(radio2) {
  return Math.PI * radio2 ;
}

let radio = 2;
alert(`El area del círculo es: ${areaCirculo(sqr(radio))}`);
// muestra 4
área del círculo

Adicionalmente, las funciones expresadas obligan a tener en orden el código y evitan comportamientos extraños causados por el hoisting.


Funciones flecha

Las funciones flecha son una forma corta de escribir funciones anónimas expresadas a partir de la versión ECMAScript 6. Para transformar una función expresada en una función flecha se realiza el siguiente procedimiento:

  1. Creamos la función expresada:

    const saludar = function () {
      alert("Hola gente");
    }
  2. Quitamos la palabra function y entre el paréntesis y la llave escribimos => (lo cual forma una flecha)

    const saludar = () => {
      alert("Hola gente");
    }
  3. Si una función flecha solo tiene una línea de código, se pueden quitar las llaves { } y la palabra return (de lo contrario no). JavaScript asume automáticamente que se quiere devolver ese valor.

    const saludar = () => alert("Hola gente");
  4. Cuando una función flecha sólo recibe un parámetro se pueden eliminar los parèntesis.
    (Si no hay parámetros o hay más de un parámetro, no.). Ejemplo:

    const saludo = persona => alert(`Hola ${persona}`);

Para ejecutar una función flecha:

saludar();
// O
saludo('Laurie');

Limitaciones de las funciones flecha

A pesar de todas las ventajas que ofrecen, las funciones flechas son limitadas y no se pueden utilizar en todas las situaciones.
Las funciones flecha () => {} son fantásticas por su sintaxis corta, pero no se diseñaron para reemplazar por completo a las funciones tradicionales. Su comportamiento interno es muy diferente. (Recordaremos estas limitaciones al crear y utilizar clases)

Ventajas de las funciones flecha

El cambio de comportamiento en las funciones flechas se debe a la sintaxis que se usa para crearla.
Al quitar la palabra clave function y usar la flecha =>, se le estás indicando al motor de JavaScript: "Quiero una función ligera".

Las funciones tradicionales (las que llevan la palabra function) son objetos muy "pesados" internamente. Cada vez que se crea una, JavaScript tiene que crear los siguientes objetos por si acaso se decide usarlos, con el consiguiente consumo de memoria y tiempo de procesamiento:

  1. Crear un objeto prototype para poder usarlo con new (en clases).
  2. Crear un array arguments asociado a la función.
  3. Configurar los mecanismos para que this cambie dinámicamente según quién ejecute la función.

Los creadores de JavaScript se dieron cuenta de que el 90% de las veces no se utilizan constructores, ni arguments, ni un this dinámico que cambie de forma impredecible. Al programar una función, la mayoría de las veces solo se desea programar simplemente un bloque de código.

De allí nacen las funciones flecha las cuales son como una versión recortada y optimizada de una función tradicional. Al quitar la palabra clave function:

Las características pesadas se pierden a cambio de un rendimiento más limpio y un this predecible que no se rompe cuando se trabaja con asincronía.

Tanto Astro como los frameworks modernos de JavaScript (como React, Angular, Vue, Svelte o incluso en el lado del servidor con Node.js/Express) utilizan en su sintaxis, funciones flecha.

También son usadas por los métodos de array (.map(), .filter(), .forEach(), .reduce(), etc.).