Arrow Functions — Declaração, funcionamento, escopos e o valor de this
O que são e como funcionam as Arrow Functions?
A nova versão do JavaScript, a ES6, trouxe novas features e dentre elas uma nova forma de criar funções usando o operador =>
. Esta nova forma de se trabalhar com funções são chamadas Arrow Functions.
Vejamos um exemplo de como declarar arrow functions:
const sum = (num1, num2) => {
return num1 + num2;
}console.log(sum(1, 2));
Podemos encurtar ainda mais a sintaxe de uma arrow function, desde que ela possua apenas uma declaração:
const sum = (num1, num2) => num1 + num2;
Ou seja, uma expressão arrow function possui uma sintaxe mais curta, semelhante as expressões lambda presente em linguagens como Java, F# entre outras.
As arrow functions possuem dois benefícios:
- São menos verbosas do que as funções tradicionais
- Seu valor de
this
é definido à partir das funções onde foram definidas. Ou seja, não é mais necessário fazerbind()
ou armazenar o estado emthat = this
;
Vejamos um exemplo:
function Exemplo(parametro) {
this.parametro = parametro;
}
Exemplo.prototype.exemploArray = function (vetor) {
'use strict';
return vetor.map(function (elemento) {
return this.parametro + elemento;
});
};
Quando tentamos acessar o this.parametro
nosso código não funciona, por que o this
está associado a função passada como argumento para a função map
.
Existe algumas possibilidades de resolvermos o problema do this
nessas ocasiões.
1° — const that = this
A solução de armazenar o valor de this
em uma variável é uma das mais comuns no desenvolvimento de aplicações JavaScript, ou seja, armazenamos o valor de this
e o acessamos de outras funções. Vejamos um exemplo:
function Exemplo(param) {
this.param = param;
}
Exemplo.prototype.exemploArray = function (vetor) {
var that = this; // Este é o ponto!
return vetor.map(function (elem) {
return that.param + elem;
});
};
Como a variável that
pode ser acessada à partir de outras funções, conseguimos acessar o valor de this
do prototype de Exemplo.
2º — Especificando o valor de this
Alguns métodos de Array tem um parâmetro extra para justamente especificarmos o valor que o this deve ter quando a função de callback é executada conforme podemos ver no código abaixo:
function Exemplo(param) {
this.param = param;
}
Exemplo.prototype.exemploArray = function (vetor) {
return vetor.map(function (elem) {
return that.param + elem;
}, this); // --> Segundo parâmetro (this) passado como argumento para a função map.
};
3º — Fazendo bind(this)
Podemos usar o método bind() para passarmos o valor de this para o objeto passado como argumento. Vejamos um exemplo:
function Exemplo(param) {
this.param = param;
}
Exemplo.prototype.exemploArray = function (vetor) {
return vetor.map(function (elem) {
return that.param + elem;
}.bind(this)); // --> função bind(this) feita na função map.
};
4° — Arrow Functions
O funcionamento da arrow function funciona de forma semelhante ao item 3. Embora tenha sido passado uma função (arrow) para o método map
, o valor de this, com a arrow function, é o da função exemploArray()
.
function Exemplo(param) {
this.param = param;
}
Exemplo.prototype.exemploArray = function (vetor) {
return vetor.map( elem => this.param + elem )
};
Escopo de uma Arrow Function e o valor de ‘this’
Antes das arrow functions todas as funções definiam seu próprio valor de this
. O valor de this
em uma arrow function é o mesmo valor do this
do escopo encapsulado ao invés de referenciar o contexto do objeto, ou seja, o objeto dentro do qual foi definida. Com isso, o escopo de uma arrow function pode ser tanto o escopo de uma função ou o escopo global, dentro de quaisquer que seja onde a arrow function foi declarada.
Vejamos um exemplo para entendermos a diferença entre o valor de this nas funções “tradicionais” e arrow functions:
// Rode esses exemplos no browser
let example = {
f1: function() {
console.log(this);
let f2 = function() {
console.log(this);
}
f2();
}
}example.f1();
A saída será: Object
, Window
e Window
;
Aqui, o valor de this dentro da função f1()
refere ao objeto example
, pois f1 é uma propriedade de example
. O this dentro da função f2() referencia ao objeto window
devido f2 ser uma propriedade do objeto window. Vejamos agora, alterando o código para arrow function para vermos o comportamento de this
:
let example = {
f1: () => {
console.log(this);
let f2 = () => console.log(this);
f2();
}
}example.f1();
A saída será: Window
, Window
e Window
;
Aqui, o valor de this dentro da função f1() referencia o valor de this do escopo global. O this dentro da função f2 referencia o valor de this da função f1() devido a função f2 ser uma propriedade de f1 e estar em seu escopo.
Considerações finais
As arrow functions não podem ser usadas como construtores, pois não podemos aplicar o operador new
a elas. Com excessão a sintaxe, valor de this e o operador new, tudo mais continua funcionando da mesma forma em ambas declarações, seja arrow function, seja funções tradicionais, ou seja, ambos são instâncias de Function.