Funciones Flecha

This is a new technology, part of the ECMAScript 2015 (ES6) standard.
This technology's specification has been finalized, but check the compatibility table for usage and implementation status in various browsers.

La expresión de función flecha tiene una sintaxis más corta que una expresión de función convencional y no vincula sus propios thisargumentssuper, o new.target. Las funciones flecha siempre son anónimas. Estas funciones son funciones no relacionadas con métodos y no pueden ser usadas como constructores.

Sintaxis

Sintaxis Básica

(param1, param2, paramN) => {declaraciones} 
(param1, param2, paramN) =>expresion
// Equivalente a: () => { return expresion; } 

// Los paréntesis son opcionales cuando sólo dispone de un argumento: singleParam => { statements } 
singleParam => expresion 

// Una función sin argumentos requiere paréntesis: 
() => { declaraciones }

Sintaxis Avanzada

// Incluir entre paréntesis el cuerpo para retornar un objeto literal:
params => ({foo: bar})

// Soporta parámetros rest y parámetros por default
(param1, param2, ...rest) => { statements }
(param1 = valorPredef1, param2, ..., paramN = valorPredefN) => { statements }

// Destructuración mediante la lista de parámetros también es soportada
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6

Consulta ejemplos de sintaxis más detallados aquí.

Descripción

Consulta también "ES6 In Depth: Arrow functions" en hacks.mozilla.org.

La inclusión de las Funciones Flecha se vieron influenciadas por dos factores: Sintaxis reducida y this no vinculable.

Funciones reducidas

En algunos patrones funcionales, se agradece disponer de funciones reducidas. Compara:

var elementos = [
  "Hidrógeno",
  "Helio",
  "Litio",
  "Beril­io"
];

var elementos2 = elementos.map(function(elemento){ return elemento.length });

var elementos3 = elementos.map( e => e.length );

this Contextual

Anterior a las funciones flecha, cada nueva función definía su propio valor de this (un nuevo objeto en el caso de un constructor, undefined en llamadas a funciones en modo estricto, el objeto contextual si la función se llama como un "método de un objeto", etc.). Lo cual resultaba molesto cuando se intentaba aplicar programación orientada a objetos.

function Persona() { 
   // El constructor Persona() define `this` como una instancia de sí mismo.   
   this.edad = 0; 
   setInterval(function crecer() { 
      // En modo no estricto, la función crecer() define `this` 
      // como el objeto global, el cual es diferente al objeto `this` 
      // definido por el constructor Persona().
      this.edad++; 
   }, 1000); 
} 

var p = new Persona();

En ECMAScript 3/5, este problema fué corregido asignándosele el valor de this a una variable por fuera de la función interna.

function Persona() {
  var self = this; // Algunas personas prefieren `that` en lugar de `self`. 
                   // Escoja cualquiera pero sea consistente.
  self.edad = 0;

  setInterval(function crecer() {
    // La función tipo callback apunta a la variable `self` la cual
    // contiene el objeto esperado.
    self.edad++;
  }, 1000);
}

Alternativamente, el método bind puede ser utilizado para crear una functión donde podremos asignar this al valor deseado, de está forma podemos pasar this a la función growUp().

Las funciones de flecha capturan el valor de this del contexto actual, por lo tanto el código funciona como se espera.

function Persona(){
  this.edad = 0;

  setInterval(() => {
    this.edad++; // |this| apunta al objeto Persona
  }, 1000);
}

var p = new Persona();

Relación con modo estricto (sctrict mode)

Debido a que this es contextual, las reglas de modo estricto asociadas a este son simplemente ignoradas.

var f = () => {'use strict'; return this};
f() === window; // o el objeto global

El resto de reglas asociadas a modo estricto aplican de forma normal.

Función de flecha invocada a través de los métodos call y apply

Debido a que en las funciones de flecha el valor de this es asignado de forma predefinida, aunque invocar una función de flecha a través de los métodos call() apply() es posible, su ejecución no tendrá en cuenta la asignación arbitraria de this:

var adder = {
  base : 1,
    
  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };
            
    return f.call(b, a);
  }
};

console.log(adder.add(1));         // Imprime 2 como es esperado
console.log(adder.addThruCall(1)); // También imprime 2 aunque se esperaba 3 

Argumentos contextuales

Las funciones de flecha no exponen un objeto arguments por lo que referenciar arguments.length, arguments[0], arguments[1], etc . resultan en errores de referencia no existente. En este caso, arguments puede hacer referencia a una variable arbitraria:

var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = () => arguments[0]; // Referencia al objeto arguments
  return f(2);
}

foo(1); // 1

Las funciones de flecha no tienen su propio objeto arguments, por lo que el  parámetro rest es la alternativa en este caso:

function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(1); // 2

Uso de la expresión yield

La expresión yield no puede ser usada dentro de una función de flecha (excepto dentro de funciones tradicionales anidadas).  Como consecuencia, las funciones de flecha no pueden ser usadas como funciones generadoras.

Retorno de objetos literales

Tenga en cuenta que retornar objetos literales usando la sintáxis simplificada => {propiedad:valor} no funciona como se esperaría:

var func = () => {  foo: 1  };               // Al llamar func() retorna undefined!
var func = () => {  foo: function() {}  };   // Error de sintaxis: SyntaxError: function statement requires a name

Eso es debido a que el código dentro de las llaves ({}) es leído como una secuencia de sentencias (p.ej foo es tratado como una etiqueta  o label y no como una propiedad del objeto literal).

En este caso, recuerde encerrar el objeto literal entre paréntesis:

var func = () => ({ foo: 1 });

Ejemplos

// Una función de flecha vacía retorna undefined
let empty = () => {};

(() => "foobar")() // retorna "foobar" 

var simple = a => a > 15 ? 15 : a; 
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;

// Métodos de arreglos como filtering, mapping mas sencillos...

var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) => a + b);  // 66
var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
var double = arr.map(v => v * 2);       // [10, 12, 26, 0, 2, 36, 46]

//Encadenamiento de promesas de manera sencilla
promise.then(a => {
  // ...
}).then(b => {
  // ...
});

 

 

 

Especificaciones

Especificación Estado Comentario
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Arrow Function Definitions' in that specification.
Standard Definición inicial.

Compatibilidad en navegadores

Característica Chrome Firefox (Gecko) IE/Edge Opera Safari
Soporte básico 45.0 22.0 (22.0)

Edge 12

32 No support
Característica Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support No support 45.0 22.0 (22.0) No support No support No support 45.0

Notas específicas para Firefox

  • Implementaciones iniciales de función flecha activaban automáticamente modo estricto. Esto ha cambiado a partir de Firefox 24 donde el uso de "use strict" es requerido.
  • La función de flecha es semánticamente diferente a la implementada en versiones anteriores de Firefox, la cual no eran estándar Expression Closures estas fueron añadidas en Firefox 3 (detalles: Javascript 1.8), para Expression Closures no asigna this al contexto this actual.
  • Antes de Firefox 39, un salto de línea (\n) era incorrectamente permitido despues de los argumentos de la función de flecha. Esto ha sido corregido para alinearse con la especificación de ES2015, por lo tanto código como () \n => {} arrojará SyntaxError a partir de la versión 39.

Temas relacionados

Etiquetas y colaboradores del documento

 Colaboradores en esta página: DiegoA1114, Omar.VzqzAc, oagarcia, davecarter
 Última actualización por: DiegoA1114,