Se você programa em JavaScript há algum tempo provavelmente já se esbarrou com alguma das seguintes funções “call
”, “apply
” ou “bind
”. À primeira vista podem ser vistas como algo complexo, porém é um grande aliado do desenvolvedor quando a expressão this
está inserida no código.
Call
O método call()
é uma função capaz de alterar o valor this
. Por padrão, o primeiro parâmetro que recebe é o valor do this
e o demais parâmetros são da função que invoca o método Call
.
No exemplo a seguir, criaremos um objeto e uma função que faz referência ao this
sem ter o this
referenciado em seu escopo.
const article = {
title: 'Descomplicando call, apply e bind',
language: 'JavaScript',
};
function print() {
console.log(`${this.title} em ${this.language}.`);
}
print();
// undefined em undefined.
Como a função print
e o objeto article
não possuem nenhuma ligação, print
vai imprimir undefined
, pois procura o this.title
e this.language
no objeto global e não os encontra.
Nota: Tentar isso no modo estrito resultaria em
Uncaught TypeError: Cannot read property 'title' of undefined
.
Nesse cenário, podemos utilizar o call
para especificar o contexto de this
do objeto article
na função.
print.call(article);
// Descomplicando call, apply e bind em JavaScript.
Apply
O Apply funciona exatamente como o método Call, porém seu segundo parâmetro recebe um Array dos parâmetros da função, enquanto o primeiro parâmetro continua recebendo o valor que será atribuído ao this
. Vejamos um novo exemplo, mas agora utilizando o apply:
function sumNumbers(firstNumber, secondNumber) {
const sum = this + firstNumber + secondNumber;
console.log(sum)
}
sumNumbers.apply(5, [2, 7]) // 14
Bind
O Bind por sua vez funciona de uma maneira diferente do call
e do apply
, ao invés de executar uma função, este retorna uma nova função. O seu primeiro parâmetro continua recebendo o valor que será atribuído ao this
e os demais argumentos serão os parâmetros que definirão os valores atribuídos da primeira função.
Vejamos um exemplo a seguir:
function sumNumbers(firstNumber,secondNumber = 0) {
const sum = this + firstNumber + secondNumber;
console.log(sum)
}
const bindResultFunction = sumNumbers.bind(5)
bindResultFunction(5) // 10
Na linha 7 com o método bind(5)
, definimos o valor de this
e com a função retornada em bindResultFunction
, definimos os valores que foram atribuídos aos parâmetros da primeira função – sumNumbers
, como o parâmetro secondNumber
foi inicializado com 0, o resultado final foi de 10
.
Agora vejamos um novo novo exemplo definindo dois valores para os parâmetros da função:
function sumNumbers(firstNumber, secondNumber) {
const sum = this + firstNumber + secondNumber;
console.log(sum)
}
const bindResultFunction = sumNumbers.bind(5, 7)
bindResultFunction(5) // 17
Arrow Functions
Arrow Functions não possuem um escopo para o this
. Em vez disso, elas passam para um próximo nível de execução.
Como no exemplo abaixo:
const article = {
title: 'Descomplicando call, apply e bind em JavaScript',
regularFunction: function() {
console.log(this.title);
},
arrowFunction: () => {
console.log(this.title);
}
}
article.regularFunction(); // "Descomplicando call, apply e bind em JavaScript"
article.arrowFunction(); // undefined
Porém, em determinados cenários pode ser útil utilizar arrow functions enquanto o this
faz referência ao contexto externo. Para esses cenários, podemos utilizar um construtor para executar a arrow function.
class Article {
constructor() {
this.title = 'Descomplicando call, apply e bind em JavaScript'
this.arrowFunction();
}
arrowFunction = () => {
console.log(this.title);
}
}
new Article() // Descomplicando call, apply e bind em JavaScript
Conclusão
Neste artigo aprendemos os diferentes valores que o this
pode receber utilizando os métodos call
, bind
e apply
.