JavaScript

20 out, 2020

Descomplicando call, apply e bind em JavaScript

Publicidade

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 callbind e apply.