A diferença entre funções tradicionais e arrow functions no javascript
Não se engane, não é só a compactibilidade e sintaxe elegante que diferem as maneiras de se declarar funções no Javascript.
As arrow functions é um recurso relativamente novo implementando no ES6 (ECMAScript 6) que, aos nossos olhos, se trata apenas de uma sintaxe mais concisa e elegante para declarar expressões de função no Javascript. Embora as funções tradicionais e as arrow functions funcionem de maneira semelhante, devemos tomar cuidado com certas diferenças que podem ser imperceptíveis.
Sintaxe
É notória a diferença da sintaxe entre os dois modelos, já que nas arrow function se torna possível reduzir consideravelmente o número de linhas presentes na declaração função, principalmente se já se trata de uma função simples. Veja exemplos:
Imagine uma função que recebe o nome de um usuário e o imprime no console. Na maneira tradicional, poderíamos declará-la da seguinte maneira:
function sayMyName(name){
console.log(`My name is ${name}!`);
}
sayMyName('Ernane'); // => My name is Ernane.
Já com as arrow functions presentes a partir do ES6, poderíamos fazer da seguinte maneira:
const sayMyName = (name) => {
console.log(`My name is ${name}`);
}
sayMyName('Ernane'); // => My name is Ernane.
Lembrando que para o caso das arrow functions, as chaves só são necessárias se uma expressão estiver presente, valendo a mesma regra para os parêntesis, já que são necessários apenas se houver mais de um argumento a ser passado. Dessa forma, poderíamos reduzir ainda mais e escrever o exemplo acima da seguinte maneira:
const sayMyName = name => console.log(`My name is ${name}`);
sayMyName('Ernane'); // => My name is Ernane.
Simples, não é? ✨ dessa forma, podemos ver como uma arrow function pode facilitar a declaração de uma determinada função por causa de sua sintaxe e ainda devolver o mesmo resultado que uma declaração comum.
Utilização da palavra-chave this
Ao contrário da declaração tradicional, as arrow functions não possuem seu próprio this elemento, pois o valor de this dentro de uma arrow function permanece o mesmo dentro de todo o ciclo de vida da função e está sempre vinculado ao valor de this na função pai tradicional mais próxima.
Isso ficou um pouco estranho? 🤔 deixe-me tentar descomplicar com um exemplo:
Retomando o exemplo utilizado no tópico anterior, imagine que possuímos um objeto pessoa
que tem seu nome definido como um dos seus atributos e possui uma função que imprime no console o nome dessa determinada pessoa. A depender do tipo de função utilizada, ela não conseguirá acessar corretamente o objeto pai que possui o atributo name procurado e, dessa forma, seu retorno será undefined
.
let person = {
name: "Ernane Ferreira",
sayMyName: () => console.log(`My name is ${this.name}.`)
};
person.sayMyName(); // => My name is .
Já para o caso da função ser declarada no modelo tradicional, o this funcionará como o esperado e obteremos corretamente o atributo buscado. 🤗
let person = {
name: "Ernane Ferreira",
sayMyName: function() {
console.log(`My name is ${this.name}.`);
}
};
person.sayMyName(); // => My name is Ernane Ferreira.
Acesso aos argumentos
O objeto arguments é uma variável local disponível dentro de todas as funções e é ela que torna possível a referência dos argumentos de uma função dentro da mesma utilizando o objeto arguments. No entanto, as arrow functions não possuem vinculo com o objeto arguments
:
const showArguments = () => console.log(arguments);
showArguments(1, 2, 3) // => ReferenceError: arguments is not defined.
No caso de uma função regular, podemos facilmente acessar uma listagem dos argumentos passados como parâmetro no momento da chamada da função:
function showArguments(){
console.log(arguments);
}
showArguments(1, 2, 3) // => Arguments(3) [1, 2, 3]
Utilizando-se do operador new
O operador new permite a criação da instância de um tipo de objeto definido pelo usuário ou de um dos tipos de objetos internos que tenham uma função construtora. As funções tradicionais são construtíveis e podem ser chamadas através do operador new. Em contrapartida, as arrow functions são chamáveis e não construtíveis, ou seja, essas funções nunca podem ser utilizadas como funções construtoras e nunca poderão ser invocadas com o operador new
.
Portanto, para esse tipo de execução em funções tradicionais, obtemos o seguinte resultado na execução:
function sayMyName(){
console.log(`My name is ${name}`);
}
new sayMyName('Ernane'); // => Ernane
Já para as arrow functions:
const sayMyName = () => console.log(`My name is ${name}`);
new sayMyName('Ernane'); // => Uncaught TypeError: sayMyName is not a constructor
Parâmetros com nomeclatura duplicada
As arrow functions não permitem o nome de parâmetros duplicados, mas as funções tradicionais permitem dependendo da aplicação ou não aplicação do modo estrito (Strict Mode) na implementação do código. Por exemplo, o javascript abaixo é totalmente válido:
function addTwoNumbers(x, x){
console.log(x+x);
}
addTwoNumbers(1,1); // => 2
Entretanto, o mesmo código com o modo estrito aplicado já não é mais válido:
'use strict';
function addTwoNumbers(x, x){
console.log(x+x);
}
// => Uncaught SyntaxError: Duplicate parameter name not allowed in this context
Na utilização de arrow functions, isso ocorre independentemente da aplicação do modo estrito. Em ambos os casos, a execução é inválida:
const addTwoNumbers = (x, x) => console.log(x+x);
// => SyntaxError: Uncaught SyntaxError: Duplicate parameter name not allowed in this context.
Dessa forma, é sempre bom termos bastante atenção quanto a utilização das arrow functions no lugar das funções tradicionais. Apesar de sua sintaxe ser muito agradável, elas possuem alguns pontos que devemos tomar cuidado para não deixar passar.
Em todo caso, é aconselhável um estudo mais aprofundado sobre o assunto. Como sempre, deixarei abaixo alguns links de recomendação para o aprofundamento da temática.
Espero que tenha gostado dessa postagem e que ela tenha te ajudado a encontrar o que você procurava! 💙
Links
Muito bacana o post, bem completo Eu só sabia sobre a relação com o objeto this, bom saber sobre a relação com os argumentos
Abraço
Muito bom, é importante apontar essas diferenças, pois tenho visto gente que usa sempre uma delas porque acha que é a única forma (ou "a melhor").
Sendo que o correto é avaliar caso a caso e usar um ou outro de acordo com o que precisa.
nunca na minha vida que eu iria suspeitar que javascript permitira repetir o parametro na função tradicional. 😬