¿Cuándo usar una función flecha en JavaScript?
() => { console.log('test'); }
function() { console.log('test'); }
¿Cuándo usar una función flecha en JavaScript?
() => { console.log('test'); }
function() { console.log('test'); }
Esta nueva sintaxis para funciones introducida en ES6 es funcionalmente equivalente a las funciones normales en la mayoría de las situaciones, sin embargo es importante notar las siguientes diferencias:
Valor de this
, las funciones normales capturan el valor de this
como el objeto global (o undefined
en modo estricto):
function Persona() {
this.edad = 0;
setInterval(function crecer() {
this.edad++; // error lógico, no se refieren a la misma variable
}, 1000);
}
Mientras que las funciones flecha capturan ese valor del scope externo inmediato:
function Persona(){
this.edad = 0;
setInterval(() => {
this.edad++; // correcto, this se refiere a una instancia de Persona
}, 1000);
}
Argumentos, las funciones normales tienen acceso a una variable especial llamada arguments
que es similar a un arreglo y contiene referencias a los argumentos que se pasan a una función:
function foo(arg1, arg2) {
console.log(arguments[0]);
}
foo("hola", "mundo"); // imprime "hola"
En las funciones flecha, arguments
se refiere a una variable en el scope exterior, si ésta variable no existe su valor es undefined
:
var arguments = 42;
var arr = () => arguments;
arr(); // 42
A pesar de esto se puede implementar una funcionalidad similar con los parámetros rest:
var foo = (...args) => {console.log(args[0])};
foo("hola", "mundo"); // Imprime "hola"
Si una función de flecha simplemente devuelve una sola línea de código, puede omitir los corchetes de la declaración y la palabra clave return. Esto le dice a la función de flecha que devuelva la declaración.
const double = (num) => num * 2;
Keyword yield
, esta palabra reservada fue introducida también en ES6 y es utilizada en las funciones generadoras, sin embargo no puede ser utilizada en las funciones flecha.
Las funciones flecha proporcionan una sintaxis más elegante y compacta al ser usadas como callbacks, por lo que pueden ser usadas casi en las mismas situaciones que las funciones normales, y probablemente serán preferidas en futuras versiones de EcmaScript, solo hay que tomar en cuenta las diferencias anteriores para no cometer errores.
Las funciones flecha o Arrow Functions no son solo una azúcar sintáctica para hacer mas fácil/elegante la declaración de función ordinaria. Hay considerables diferencias entre ambas que pueden hacer que un programa no funcione como se espera y no son intercambiables para muchos casos.
Por esto supongo que la pregunta completa es ¿cuando usarlas y cuando no?
En el siguiente bloque, son intercambiables por que son funciones puras (que su resultado no depende de una variable externa). En cuando performance, son prácticamente iguales.
// declaracion de funcion
var nombres = personas.map(function(p){ return p.nombre });
// funcion flecha, este es un buen caso de uso
var nombres = personas.map(p => p.nombre);
Las funciones flecha se evalúan como parte del lexical scope que las contiene, por esto this
y arguments
no son instancias propias de la función flecha sino que son las instancias de la función contenedora. Este tipo de funciones no son intercambiables, deberás reescribir partes del cuerpo de la función si quieres cambiar de una sintaxis a la otra.
Considera este otro bloque:
// ECMAScript 5, usando una declaración de función.
function contadorDeSegundos() {
var that = this;
this.contar = 0;
setInterval(function() {
that.contar++;
}, 1000);
}
/// ECMAScript 2015, con arrow functions
function contadorDeSegundos() {
this.contar = 0;
setInterval(() => { this.contar++ }, 1000);
}
Como ves aquí otra vez el código es mas compacto, pero el comportamiento de this
es muy diferente.
Como ya se estableció, la funciones flecha no exponen el objeto arguments
, por lo tanto si necesitas acceso al mismo no puedes utilizarlas. Ten en cuenta que si la función flecha la declaras dentro de otra función, estarías accediendo al arguments
de la función contenedora (si hubiese una). Por eso se dice las funciones flecha utilizan lexical arguments. Es decir, que ven el objeto arguments
que esta en el lexical scope.
A nivel global:
var f = () => { console.log(arguments.length) }
f();
// produce: Uncaught ReferenceError: arguments is not defined(…)
var f2 = function() { console.log(arguments.length) }
f2();
// produce: 0
La palabra clave yield
no esta permitida en funciones flecha. Estas funciones no pueden ser funciones generador (sin embargo pueden contener funciones generador).