Funciones flecha en JavaScript: diferencias reales con function y cuándo usarlas

Las funciones flecha, introducidas en ES6, no son solo una forma más corta de escribir funciones. Tienen diferencias semánticas importantes con las funciones declaradas con function: no tienen su propio this, no tienen arguments, no pueden ser constructores y no se pueden usar como generadores. Conocer cuándo usarlas y cuándo evitarlas es lo que marca la diferencia.

Sintaxis: de larga a compacta

Las funciones flecha permiten escribir funciones de una forma más concisa, especialmente cuando el cuerpo es una sola expresión:

// Función tradicional
function sumar(a, b) {
  return a + b;
}

// Arrow function equivalente
const sumarFlecha = (a, b) => a + b;

// Con un solo parámetro, los paréntesis son opcionales
const doble = x => x * 2;

// Sin parámetros, los paréntesis son obligatorios
const saludar = () => 'Hola';

// Cuerpo con bloque: necesita return explícito
const clamp = (val, min, max) => {
  if (val < min) return min;
  if (val > max) return max;
  return val;
};

// Devolver un objeto literal: envolver en paréntesis
const crearUsuario = (nombre, edad) => ({ nombre, edad });
console.log(crearUsuario('Ana', 30));  // {nombre: 'Ana', edad: 30}
// Sin paréntesis, las llaves se interpretan como bloque

La diferencia clave: this léxico

Las funciones flecha capturan el this del scope donde se definen (léxico), en lugar de determinarlo en el momento de la llamada. Esto las hace perfectas para callbacks donde necesitas preservar el contexto:

// Bug con function tradicional:
class Temporizador {
  constructor() {
    this.segundos = 0;
  }

  iniciar() {
    setInterval(function() {
      this.segundos++;  // ERROR: this es window/undefined
    }, 1000);
  }
}

// Correcto con arrow function:
class TemporizadorCorrecto {
  constructor() {
    this.segundos = 0;
  }

  iniciar() {
    setInterval(() => {
      this.segundos++;  // this es la instancia de TemporizadorCorrecto
      console.log(this.segundos);
    }, 1000);
  }
}

// También en promesas:
class ApiService {
  constructor(url) {
    this.url = url;
  }

  obtenerDatos() {
    return fetch(this.url)
      .then(r => r.json())           // this heredado
      .then(datos => {
        console.log(this.url, datos);  // this heredado
        return datos;
      });
  }
}

No tienen arguments

Las funciones flecha no tienen su propio objeto arguments. Si necesitas argumentos variables en una arrow function, usa rest parameters:

function tradicional() {
  console.log(arguments);  // Arguments [1, 2, 3]
}
tradicional(1, 2, 3);

const flecha = () => {
  console.log(arguments);  // ReferenceError (o arguments del scope externo)
};

// Correcto: usar rest
const flechaRest = (...args) => {
  console.log(args);  // [1, 2, 3] — array real
  return args.reduce((a, b) => a + b, 0);
};
console.log(flechaRest(1, 2, 3));  // 6

No se pueden usar como constructores

Las funciones flecha no tienen un [[Construct]] interno. Intentar usarlas con new lanza un TypeError:

const Persona = (nombre) => {
  this.nombre = nombre;
};

const p = new Persona('Ana');  // TypeError: Persona is not a constructor

// Para constructores, usa function o class:
class PersonaClase {
  constructor(nombre) {
    this.nombre = nombre;
  }
}

Cuándo NO usar funciones flecha

Hay contextos donde las arrow functions son una mala elección:

// MAL: método de objeto (this no apunta al objeto)
const objeto = {
  valor: 42,
  obtener: () => this.valor  // this es el global, no objeto
};
console.log(objeto.obtener());  // undefined

// BIEN: method shorthand
const objetoCorrecto = {
  valor: 42,
  obtener() { return this.valor; }
};

// MAL: event listener donde necesitas this como elemento DOM
boton.addEventListener('click', () => {
  this.style.color = 'red';  // this no es el botón
});

// BIEN: function tradicional
boton.addEventListener('click', function() {
  this.style.color = 'red';  // this es el botón
});

// MAL: métodos de prototipo si usan this
Array.prototype.doble = () => this.map(x => x * 2);
// BIEN:
Array.prototype.doble = function() { return this.map(x => x * 2); };

La guía práctica: usa arrow functions para callbacks, métodos de array (map, filter, etc.), funciones de utilidad puras y cualquier lugar donde necesites preservar el this externo. Usa function para métodos de objeto, constructores, manejadores de eventos que necesiten this y funciones que usen arguments.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP