call(), apply() e bind() - Os Três Patetas do JavaScript
Tags: javascript
Published: 2023-06-02 00:38:57

Olá pessoas, como estão? Baummm ? Espero que sim. Hoje vamos falar sobre três amigos inseparáveis do JavaScript: `call()`, `apply()` e `bind()`.

![happy javascript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fpsgy8haa5y4t9xwo6j.gif) 

Se você já se deparou com esses três, pode ter ficado um pouco confuso, mas não se preocupe, vou tentar aqui clarear as ideias. Vamos lá! 

## Método `call()`

O método `call()` é uma verdadeira mão na roda quando você precisa invocar uma função e definir um valor específico para o `"this"`. Ele permite que você chame uma função, passando um objeto para o qual o `"this"` será definido dentro da função. 

Esse método `call()` é utilizado para invocar uma função com um determinado contexto de execução e uma lista de argumentos passados separadamente. Ele aceita um objeto como primeiro parâmetro, que será o valor de this dentro da função chamada. Em seguida, você pode passar os argumentos da função separadamente como argumentos subsequentes. Bora de um exemplo:

```javascript
function greeting() {
  console.log(`Olá, ${this.name}! Bem-vindo(a) ao ${this.local}!`);
}

const person = {
  name: 'Ana',
  local: 'restaurante'
};

const otherPerson = {
  name: 'Carlos',
  local: 'hotel'
};

greeting.call(person); // Olá, Ana! Bem-vindo(a) ao restaurante!
greeting.call(otherPerson); // Olá, Carlos! Bem-vindo(a) ao hotel!
```

Neste exemplo, temos uma função `greeting()` que imprime uma mensagem de boas-vindas personalizada com base nas propriedades nome e local. Em seguida, temos dois objetos: `person` e `otherPerson`, cada um com suas próprias propriedades nome e local.

Ao utilizar o método `call()` com a função `greeting()`, passamos como argumento o objeto no qual queremos definir o valor de `this`. Quando chamamos `greeting.call(person)`, a função `greeting()` é executada no contexto de pessoa, e a mensagem exibida é "Olá, Ana! Bem-vindo(a) ao restaurante!". Da mesma forma, ao chamar `greeting.call(otherPerson)`, a função é executada no contexto de `otherPerson`, e a mensagem exibida é "Olá, Carlos! Bem-vindo(a) ao hotel!".

Dessa forma, o método `call()` permite que você chame uma função e defina o valor de `this` explicitamente, permitindo a reutilização de funções em diferentes contextos.

## Método `apply()`

Já o método `apply()` é muito parecido com o `call()`, mas com uma diferença sutil. Enquanto o `call()` espera os argumentos separados por vírgula, o `apply()` espera que os argumentos sejam fornecidos como um array. O primeiro parâmetro ainda representa o valor de `this` dentro da função. 
Ele é útil quando você possui uma função que espera receber seus argumentos como um array ou um objeto de argumentos. Vamos ver um exemplo para ficar mais claro:

```javascript
const person = {
  name: 'João',
  greeting: function(greeting, pointing) {
    console.log(greeting + ' ' + this.name + pointing);
  }
};

const args = ['Olá', '!'];
person.greeting.apply(person, args); // Olá João!
```

Neste exemplo, o método `greeting` do objeto pessoa é invocado usando o método `apply()`. O valor de `this` é definido como person para garantir que o `this.name` se refira à propriedade nome do objeto `person`. Os argumentos são passados como um `array['Olá', '!']`, resultando na saída `"Olá João!"`.

## Método `bind()`

Por fim, temos o método `bind()`. Diferente dos outros dois, o `bind()` não invoca a função imediatamente. Em vez disso, ele retorna uma nova função, vinculada ao objeto que você passou como argumento. Dessa forma, você pode chamar essa nova função posteriormente. Ele não executa a função imediatamente, mas permite que você a invoque posteriormente. Além disso, você também pode pré-definir argumentos para a função retornada. Confuso? Vamos ver um exemplo:

```javascript
const car = {
  brand: "Fiat",
  model: "Uno",
  displayCar: function() {
    console.log(`Brand: ${this.brand}, Model: ${this.model}`);
  }
};

const displayCaptur = car.displayCar.bind(car);
displayCaptur();
```

Nesse exemplo, temos um objeto carro com um método `displayCar()`. Usando o `bind()`, criamos uma nova função `displayCaptur` que está vinculada ao objeto carro. Quando chamamos a função `displayCaptur()`, ela exibe a marca e o modelo do carro.

## Resumindo....

Então, galera, é isso! Agora vocês estão por dentro das diferenças entre `call()`, `apply()` e `bind()`. 

Usem esses três patetas do JavaScript com sabedoria e aproveitem ao máximo suas funcionalidades. O `call()` é perfeito quando você precisa invocar uma função e definir o valor do `"this"` explicitamente, o `apply()` é ótimo quando você quer passar os argumentos como um array e definir o valor do `"this"`, enquanto o `bind()` permite vincular um objeto a uma nova função para ser chamada posteriormente.

Esses métodos podem ser muito úteis em várias situações de programação, especialmente quando você lida com objetos e precisa controlar o contexto do `"this"` e os argumentos da função. Agora você tem essas poderosas ferramentas no seu arsenal de desenvolvedor.

Então, pessoal, não se preocupem se os métodos `call()`, `apply()` e `bind()` parecerem um pouco confusos no início. Com o tempo e a prática, vocês irão se acostumar a utilizá-los e aproveitar todos os benefícios que eles têm a oferecer. Mãos à obra e continuem explorando as maravilhas do JavaScript!