Qual é a diferença entre usar call
e apply
chamar uma função?
var func = function() {
alert('hello!');
};
func.apply();
vs func.call();
Existem diferenças de desempenho entre os dois métodos mencionados acima? Quando é melhor usar call
repetidamente apply
e vice-versa?
javascript
performance
function
dynamic
John Duff
fonte
fonte
a
em candidatar-se a matriz de argumentos ec
em chamar por colunas de argumentos.fn(...input)
onde input é uma matriz. developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…Respostas:
A diferença é que
apply
permite invocar a funçãoarguments
como uma matriz;call
requer que os parâmetros sejam listados explicitamente. Um acelerador é útil " A para um rray e C para C omma."Consulte a documentação da MDN sobre aplicar e ligar .
Pseudo-sintaxe:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
Há também, a partir do ES6, a possibilidade de
spread
o array ser usado com acall
função, você pode ver as compatibilidades aqui .Código de amostra:
fonte
[]
é chamado de matriz ,{}
é chamado de objeto .Array.prototype.slice.call(arguments)
ou[].slice.call(arguments)
. apply faz sentido se você tiver os argumentos em uma matriz, por exemplo, em uma função que chama outra função com (quase) os mesmos parâmetros. Recomendação Use uma chamada de função normalfuncname(arg1)
se isso for o que você precisa e salve a chamada e solicite as ocasiões especiais em que você realmente precisa delas.call
eapply
usa dois parâmetros. O primeiro argumento daapply' and
função call` deve ser o objeto do proprietário e o segundo parâmetro serão parâmetros separados por matriz ou vírgula, respectivamente. Se você passarnull
ouundefined
como primeiro argumento, em seguida, no modo não-estrito eles são substituídos por objeto global ou sejawindow
K. Scott Allen tem uma boa redação sobre o assunto.
Basicamente, eles diferem na maneira como lidam com argumentos de função.
Assim:
fonte
call
mas é um requisito paraapply
Para responder à parte sobre quando usar cada função, use
apply
se você não souber o número de argumentos que estará passando ou se eles já estiverem em uma matriz ou objeto semelhante a matriz (como oarguments
objeto para encaminhar seus próprios argumentos. Use decall
outra forma, pois não há necessidade de agrupar os argumentos em uma matriz.Quando não estou passando nenhum argumento (como o seu exemplo), prefiro
call
já que estou chamando a função.apply
implicaria que você está aplicando a função aos argumentos (inexistentes).Não deve haver diferenças de desempenho, exceto talvez se você usar
apply
e agrupar os argumentos em uma matriz (por exemplo, emf.apply(thisObject, [a, b, c])
vez def.call(thisObject, a, b, c)
). Eu não o testei, então pode haver diferenças, mas seria muito específico do navegador. É provável quecall
seja mais rápido se você ainda não tiver os argumentos em uma matriz eapply
mais rápido se tiver.fonte
Aqui está um bom mnemônico. A plicar usa A rrays e A lways leva um ou dois argumentos. Quando você usa C, tudo o que você precisa é C ou o número de argumentos.
fonte
apply
é necessário. Não sei ao certo por que alguém chamaráapply
oucall
sem um parâmetro. Parece que alguém está tentando descobrir por que aqui stackoverflow.com/questions/15903782/…Embora esse seja um tópico antigo, eu só queria salientar que o .call é um pouco mais rápido que o .apply. Eu não posso te dizer exatamente o porquê.
Consulte jsPerf, http://jsperf.com/test-call-vs-apply/3
[
UPDATE!
]Douglas Crockford menciona brevemente a diferença entre os dois, o que pode ajudar a explicar a diferença de desempenho ... http://youtu.be/ya4UHuXNygM?t=15m52s
Apply usa uma matriz de argumentos, enquanto Call usa zero ou mais parâmetros individuais! Ah, ah!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
fonte
Segue um extrato de Closure: The Definitive Guide, de Michael Bolin . Pode parecer um pouco demorado, mas está saturado de muita percepção. Do "Apêndice B. Conceitos de JavaScript frequentemente incompreendidos":
O que
this
se refere quando uma função é chamadaAo chamar uma função do formulário
foo.bar.baz()
, o objetofoo.bar
é chamado de receptor. Quando a função é chamada, é o receptor que é usado como o valor parathis
:Se não houver um receptor explícito quando uma função é chamada, o objeto global se torna o receptor. Conforme explicado em "goog.global" na página 47, window é o objeto global quando o JavaScript é executado em um navegador da web. Isso leva a um comportamento surpreendente:
Mesmo assim,
obj.addValues
e sef
referem à mesma função, eles se comportam de maneira diferente quando chamados, porque o valor do receptor é diferente em cada chamada. Por esse motivo, ao chamar uma função que se referethis
, é importante garantir quethis
o valor correto seja chamado. Para ser claro, sethis
não fosse referenciado no corpo da função, o comportamento def(20)
eobj.addValues(20)
seria o mesmo.Como as funções são objetos de primeira classe em JavaScript, elas podem ter seus próprios métodos. Todas as funções possuem os métodos
call()
eapply()
que permitem redefinir o receptor (ou seja, o objeto a quethis
se refere) ao chamar a função. As assinaturas de método são as seguintes:Observe que a única diferença entre
call()
eapply()
é quecall()
recebe os parâmetros da função como argumentos individuais, enquanto osapply()
recebe como uma única matriz:As seguintes chamadas são equivalentes, como
f
eobj.addValues
se referem à mesma função:No entanto, como
call()
nemapply()
usa o valor de seu próprio receptor para substituir o argumento do receptor quando não for especificado, o seguinte não funcionará:O valor de
this
nunca pode sernull
ouundefined
quando uma função é chamada. Quandonull
ouundefined
é fornecido como receptor paracall()
ouapply()
, o objeto global é usado como o valor para o receptor. Portanto, o código anterior tem o mesmo efeito colateral indesejável de adicionar uma propriedade nomeadavalue
ao objeto global.Pode ser útil pensar em uma função como não tendo conhecimento da variável à qual está atribuída. Isso ajuda a reforçar a ideia de que o valor disso será vinculado quando a função for chamada e não quando for definida.
Fim da extração.
fonte
additionalValues
não é referenciado dentroobj.addValues
do corpovar f = obj.addValues;
tornavar f = obj.addValues.bind(obj)
- se e agora f (20) funcionaria sem ter que usar a chamada ou aplicar todas as vezes.Às vezes, é útil que um objeto peça emprestada a função de outro objeto, o que significa que o objeto emprestado simplesmente executa a função emprestada como se fosse sua.
Um pequeno exemplo de código:
Esses métodos são muito úteis para fornecer aos objetos funcionalidade temporária.
fonte
console.log
check-out: O que é console.log e como eu o uso?Outro exemplo com Call, Apply e Bind. A diferença entre Call e Apply é evidente, mas o Bind funciona assim:
}
fonte
Gostaria de mostrar um exemplo, onde o argumento 'valueForThis' é usado:
** detalhes: http://es5.github.io/#x15.4.4.7 *
fonte
Call () recebe argumentos separados por vírgula, ex:
.call(scope, arg1, arg2, arg3)
e apply () recebe uma matriz de argumentos, ex:
.apply(scope, [arg1, arg2, arg3])
Aqui estão mais alguns exemplos de uso: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
fonte
Nos documentos MDN sobre Function.prototype.apply () :
Nos documentos MDN sobre Function.prototype.call () :
Em Function.apply e Function.call em JavaScript :
Exemplo de código:
Veja também este violino .
fonte
A diferença fundamental é que
call()
aceita uma lista de argumentos , enquantoapply()
aceita uma única matriz de argumentos .fonte
Aqui está um post pequeno, escrevi sobre isso:
http://sizeableidea.com/call-versus-apply-javascript/
fonte
A diferença é que
call()
leva os argumentos da função separadamente eapply()
leva os argumentos da função em uma matriz.fonte
Podemos diferenciar chamadas e aplicar métodos como abaixo
CHAMADA: Uma função com argumento fornece individualmente. Se você conhece os argumentos a serem transmitidos ou não há argumentos a serem transmitidos, pode usar call.
APLICAR: Chame uma função com argumento fornecido como uma matriz. Você pode usar o apply se não souber quantos argumentos serão transmitidos para a função.
Há uma vantagem de usar a aplicação sobre chamada, não precisamos alterar o número de argumentos, apenas podemos alterar uma matriz que é passada.
Não há grande diferença no desempenho. Mas podemos dizer que a chamada é um pouco mais rápida do que comparar para aplicar, porque uma matriz precisa avaliar no método apply.
fonte
A diferença entre esses métodos e os métodos é como você deseja passar os parâmetros.
"A para array e C para vírgula" é um mnemônico útil.
fonte
Chamar e aplicar ambos são usados para forçar o
this
valor quando uma função é executada. A única diferença é quecall
receben+1
argumentos onde 1 éthis
e'n' arguments
.apply
leva apenas dois argumentos, um éthis
o outro é matriz de argumentos.A vantagem que vejo
apply
acimacall
é que podemos delegar facilmente uma chamada de função para outra função sem muito esforço;Observe como é fácil delegado
hello
parasayHello
usarapply
, mas comcall
isso é muito difícil de alcançar.fonte
Mesmo assim
call
eapply
obtendo a mesma coisa, acho que há pelo menos um lugar onde você não pode usar,call
mas só pode usá-loapply
. É quando você deseja dar suporte à herança e deseja chamar o construtor.Aqui está uma função que permite criar classes que também suporta a criação de classes estendendo outras classes.
fonte
Resumo:
Ambos
call()
eapply()
são métodos localizados emFunction.prototype
. Portanto, eles estão disponíveis em todos os objetos de função através da cadeia de protótipos. Amboscall()
eapply()
podem executar uma função com um valor especificado dethis
.A principal diferença entre
call()
eapply()
é a maneira como você deve passar argumentos para ele. Em amboscall()
eapply()
você passa como primeiro argumento o objeto para o qual deseja ser o valorthis
. Os outros argumentos diferem da seguinte maneira:call()
você tem que colocar os argumentos normalmente (a partir do segundo argumento)apply()
você tem que passar na matriz de argumentos.Exemplo:
Por que eu precisaria usar essas funções?
O
this
valor pode ser complicado às vezes em javascript. O valor dethis
determinado quando uma função é executada e não quando uma função é definida. Se nossa função depende de umathis
ligação correta , podemos usarcall()
eapply()
impor esse comportamento. Por exemplo:fonte
A principal diferença é que, usando call, podemos alterar o escopo e passar argumentos normalmente, mas apply permite chamá-lo usando argumentos como uma matriz (passá-los como uma matriz). Mas em termos do que eles devem fazer no seu código, eles são bem parecidos.
Então, como você vê, não há uma grande diferença, mas ainda assim, há casos em que preferimos usar call () ou apply (). Por exemplo, observe o código abaixo, que encontra o menor e o maior número em uma matriz do MDN, usando o método apply:
Portanto, a principal diferença é a maneira como transmitimos os argumentos
:
Aplique:
fonte
Deixe-me adicionar um pequeno detalhe a isso.
essas duas chamadas são quase equivalentes:
Há apenas uma pequena diferença:
Portanto, essas chamadas se complementam. Onde esperamos um iterável ,
call
funciona, onde esperamos um array ,apply
funciona.E para objetos que são tanto iterable e gama-like , como uma matriz real, nós tecnicamente poderia usar qualquer um deles, mas aplicam-se provavelmente será mais rápido porque a maioria dos motores de JavaScript otimizá-lo internamente melhor.
fonte