Métodos call() e apply() — Uso, invocação e contexto

Começo o 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);

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ó… Até a próxima!