Métodos call() e apply()

Uso, invocação e contexto

Posted by Raphael Lima on 12-09-2016

Começo este post com a seguinte pergunta:

Podemos forçar o contexto da função fazendo com que ele seja o objeto proprietário do método e não o objeto associado ao evento?
R: Sim, podemos!

Algo que difere os tipos de invocação de funções é que objetos acabam se tornando o contexto da função e são referenciados pelo parâmetro this passado de forma implícita para a função executora. Por exemplo, caso a invocação da função seja através de um construtor, isso representará uma nova instância de objeto recém-criado.

O JavaScript nos fornece um meio de invocarmos uma função e definirmos de maneira explícita qual objeto queremos como contexto da função. Isso é feito através dos métodos de funções call() e apply(). Métodos de funções podem soar um pouco estranho, mas, assim como objetos de primeira classe, em JavaScript, funções possuem propriedades como qualquer outro objeto, portanto, métodos também podem ser considerados propriedades de uma função.

A real diferença entre essas funções é que, para invocarmos uma função utilizando o método call() passamos como primeiro parâmetro o objeto que será o contexto da função, e uma lista de argumentos separados por vírgula. Já o método apply(), recebe apenas dois argumentos, o primeiro é o objeto a ser o contexto da função e diferente da função call(), passamos um array de valores a serem utilizados como argumentos de invocação como segundo argumento.

Veja a seguir um exemplo prático das duas funções.

function sum() {
  var result = 0;
  for(var i = 0; i < arguments.length; i++) {
    result += arguments[i];
  }
  this.result = result;
}

var object1 = {};
var object2 = {};

sum.apply(object1, [9,8,7,6]);
sum.call(object2, 5, 4, 3, 2);

Se você achou estranho o fato de a função sum() não receber argumentos em sua definição e mesmo assim conseguir receb-los, dê uma olhada nos textos da sequência “Funções JavaScript: Por quê é fundamental dominá-las?”

Para entendermos melhor o código acima, vamos analisá-lo por partes… Temos uma função sum() responsável por somar todos os argumentos recebidos e armazenar o resultado na propriedade result no contexto da função. Posteriormente, criamos dois objetos, var object1 = {} e var object2 = {} que foram passados como primeiro argumento para os métodos apply() e call(), respectivamente e os utilizaremos como contexto de função. Podemos testar o código acima através da função assert() e veremos que o contexto da função é alterado conforme o objeto passado como primeiro argumento.

assert(object1.result === 30, "Objeto 1 é o contexto");
assert(object2.result === 14, "Objeto 2 é o contexto");

Diante deste exemplo simples, vimos que os métodos call() e apply() nos permite definir o contexto da função no objeto que quisermos. Ou seja, o valor de this será exatamente o objeto passado como primeiro argumento.

Por hoje é só… Deixem seus comentários e até a próxima :)