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) => { sentencias }
(param1, param2, …, paramN) => expresion
// Equivalente a: () => { return expresion; } 

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

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

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) => { sentencias }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { sentencias }

// 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

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

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

elementos.map(function(elemento){ 
    return elemento.length;
});  // [8, 6, 7, 9]

elementos.map((elemento) => {
  return elemento.length;
}); // [8, 6, 7, 9]

elementos.map(({length}) => length); // [8, 6, 7, 9]

this Contextual

Antes 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().

Una función flecha no tiene su propio this; utiliza el valor del contexto de ejecución que la contiene. Por lo que, en el siguiente código, this dentro de la función que se pasa a setInterval tiene el mismo valor que this en la función que la envuelve:

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 del modo estricto asociadas a this 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

Dado que las funciones flecha no tienen su propio this, los métodos call() y apply() sólo pueden pasar parámetros. thisArg es ignorado:

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 tienen su propio objeto arguments. Por lo que, en este ejemplo, arguments es simplemente una referencia a los argumentos del contexto superior:

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

arr(); // 42

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

foo(1); // 1

En la mayoría de los casos, el uso de parámetros rest es una buena alternativa al uso del objeto arguments:

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

foo(1); // 11

Funciones Flecha usadas como métodos

Como se ha indicado anteriormente, las expresiones de función de flecha son las más adecuadas para funciones que no son métodos. Veamos qué pasa cuando intentamos usarlos como métodos:

'use strict';

var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
}

obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}

Las funciones flecha no tienen su propio this. Otro ejemplo usando Object.defineProperty():

'use strict';

var obj = {
  a: 10
};

Object.defineProperty(obj, 'b', {
  get: () => {
    console.log(this.a, typeof this.a, this);
    return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
  }
});

Uso del operador new

Las funciones flecha no pueden ser usadas como constructores, arrojarán un error cuando sea usada con new.

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

Uso de la propiedad prototype

Las funciones flecha no tienen una propiedad de prototipo prototype.

var Foo = () => {};
console.log(Foo.prototype); // undefined

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.

Cuerpo de una función

Las funciones flecha pueden tener ya sea un "cuerpo conciso" o el usual "cuerpo de bloque".

En un cuerpo conciso, solo una expreción es especificada, la cual convierte el valor de retorno explicito. en un bloque cuerpo, tu tienes que usar una declaracion de retorno explicita.

var func = x => x * x;                  
// sintaxis de cuerpo conciso, el "return" está implícito

var func = (x, y) => { return x + y; }; 
// con cuerpo de bloque, se necesita "return" explícito

Retorno de objetos literales

Tenga en cuenta que retornar objetos literales usando la sintáxis simplificada params => objeto:literal} 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 });

Saltos de línea

Una función flecha no puede contener un salto de linea entre sus parámetros y su flecha.

var func = ()
           => 1; 
// SyntaxError: expected expression, got '=>'

Orden de parseo

Aunque la flecha en una función flecha no es un operador, las funciones flecha tienen reglas de parseo especiales que interactúan de forma diferente con la precedencia de operadores en comparación con las funciones normales.

let callback;

callback = callback || function() {}; // ok

callback = callback || () => {};      
// SyntaxError: invalid arrow-function arguments

callback = callback || (() => {});    // ok

Más ejemplos

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

(() => "foobar")() 
// retorna "foobar" 
// (this is an Immediately Invoked Function Expression 
// see 'IIFE' in glossary)

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 => {
  // ...
});

// Funciones de flecha sin parámetros son más fáciles de visualizar
setTimeout( () => {
  console.log('Yo voy primero');
  setTimeout( () => {
    // deeper code
    console.log('Yo voy despues');
  }, 1);
}, 1);

Especificaciones

Especificación Estado Comentario
ECMAScript 2015 (6th Edition, ECMA-262)
La definición de 'Arrow Function Definitions' en esta especificación.
Standard

Definición inicial.

ECMAScript Latest Draft (ECMA-262)
La definición de 'Arrow Function Definitions' en esta especificación.

Draft  

Compatibilidad en navegadores

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Soporte básico45 Si221 2 No3210
Trailing comma in parameters58 ?52 No45 ?
FeatureAndroid webviewChrome para AndroidEdge mobileFirefox para AndroidOpera AndroidiOS SafariSamsung Internet
Soporte básico4545 Si221 232105.0
Trailing comma in parameters5858 ?5245 ?7.0

1. The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.

2. Prior to Firefox 39, a line terminator (\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \n => {} will now throw a SyntaxError in this and later versions.

Vea también

Etiquetas y colaboradores del documento

Última actualización por: fcanellas,