¿Cuál es la diferencia entre usar call
e apply
invocar una función?
var func = function() {
alert('hello!');
};
func.apply();
vs func.call();
¿Existen diferencias de rendimiento entre los dos métodos antes mencionados? ¿Cuándo es mejor utilizar call
más apply
y viceversa?
javascript
performance
function
dynamic
John Duff
fuente
fuente
a
en solicitar matriz de argumentos yc
en solicitar columnas de argumentos.fn(...input)
donde input es una matriz. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Respuestas:
La diferencia es que le
apply
permite invocar la funciónarguments
como una matriz;call
requiere que los parámetros se enumeren explícitamente. Un mnemotécnico útil es " A para una matriz y C para c omma".Consulte la documentación de MDN sobre solicitud y llamada .
Pseudo sintaxis:
theFunction.apply(valueForThis, arrayOfArgs)
theFunction.call(valueForThis, arg1, arg2, ...)
También existe, a partir de ES6, la posibilidad de que
spread
la matriz se use con lacall
función, puede ver las compatibilidades aquí .Código de muestra:
fuente
[]
se llama matriz ,{}
se llama objeto .Array.prototype.slice.call(arguments)
o[].slice.call(arguments)
. apply tiene sentido si tiene los argumentos en una matriz, por ejemplo, en una función que llama a otra función con (casi) los mismos parámetros. Recomendación Use una llamada de función normalfuncname(arg1)
si eso hace lo que necesita, y guarde la llamada y solicite esas ocasiones especiales cuando realmente las necesite.call
yapply
toma dos parámetros. El primer argumento de laapply' and
función call` debe ser el objeto propietario y el segundo parámetro será una matriz o parámetros separados por comas, respectivamente. Si pasanull
oundefined
como primer argumento, entonces en modo no estricto, se reemplazan con un objeto global, es decirwindow
K. Scott Allen tiene una buena reseña sobre el asunto.
Básicamente, difieren en cómo manejan los argumentos de la función.
Entonces:
fuente
call
pero sí un requisitoapply
Para responder la parte sobre cuándo usar cada función, úsela
apply
si no sabe el número de argumentos que pasará, o si ya están en una matriz o en un objeto similar a una matriz (como elarguments
objeto para reenviar sus propios argumentos. Use locall
contrario, ya que no hay necesidad de ajustar los argumentos en una matriz.Cuando no estoy pasando ningún argumento (como su ejemplo), prefiero
call
ya que estoy llamando a la función.apply
implicaría que está aplicando la función a los argumentos (inexistentes).No debería haber ninguna diferencia de rendimiento, excepto tal vez si usa
apply
y ajusta los argumentos en una matriz (por ejemplo, enf.apply(thisObject, [a, b, c])
lugar def.call(thisObject, a, b, c)
). No lo he probado, por lo que podría haber diferencias, pero sería muy específico del navegador. Es probable quecall
sea más rápido si aún no tiene los argumentos en una matriz yapply
más rápido si lo tiene.fuente
Aquí hay una buena mnemónica. Una aplicación utiliza las matrices A y A siempre toma uno o dos argumentos. Cuando se utiliza C todo lo que tiene a C porte el número de argumentos.
fuente
apply
se requiere ni el primer ni el segundo parámetro de . Sin embargo, no estoy seguro de por qué uno llamaráapply
ocall
sin un parámetro. Parece que alguien está tratando de averiguar por qué aquí stackoverflow.com/questions/15903782/…Si bien este es un tema antiguo, solo quería señalar que .call es un poco más rápido que .apply. No puedo decirte exactamente por qué.
Ver jsPerf, http://jsperf.com/test-call-vs-apply/3
[
UPDATE!
]Douglas Crockford menciona brevemente la diferencia entre los dos, lo que puede ayudar a explicar la diferencia de rendimiento ... http://youtu.be/ya4UHuXNygM?t=15m52s
¡Apply toma una variedad de argumentos, mientras que Call toma cero o más parámetros individuales! Ah hah!
.apply(this, [...])
.call(this, param1, param2, param3, param4...)
fuente
Sigue un extracto de Cierre: La guía definitiva de Michael Bolin . Puede parecer un poco largo, pero está saturado con mucha información. Del "Apéndice B. Conceptos de JavaScript frecuentemente malinterpretados":
A qué se
this
refiere cuando se llama una funciónCuando se llama a una función de la forma
foo.bar.baz()
, el objetofoo.bar
se denomina receptor. Cuando se llama a la función, es el receptor el que se utiliza como valor parathis
:Si no hay un receptor explícito cuando se llama a una función, el objeto global se convierte en el receptor. Como se explica en "goog.global" en la página 47, la ventana es el objeto global cuando JavaScript se ejecuta en un navegador web. Esto lleva a un comportamiento sorprendente:
A pesar de que
obj.addValues
yf
se refieren a la misma función, se comportan de manera diferente cuando se llama así porque el valor del receptor es diferente en cada llamada. Por esta razón, cuando se llama a una función que hace referenciathis
, es importante asegurarse de quethis
tendrá el valor correcto cuando se llame. Para ser claros, sithis
no se hiciera referencia en el cuerpo de la función, el comportamiento def(20)
yobj.addValues(20)
sería el mismo.Como las funciones son objetos de primera clase en JavaScript, pueden tener sus propios métodos. Todas las funciones tienen los métodos
call()
yapply()
permiten redefinir el receptor (es decir, el objeto al que sethis
refiere) cuando se llama a la función. Las firmas del método son las siguientes:Tenga en cuenta que la única diferencia entre
call()
yapply()
es quecall()
recibe los parámetros de la función como argumentos individuales, mientras que losapply()
recibe como una sola matriz:Las siguientes llamadas son equivalentes, como
f
yobj.addValues
se refieren a la misma función:Sin embargo, dado que
call()
niapply()
utiliza el valor de su propio receptor para sustituir el argumento del receptor cuando no está especificado, lo siguiente no funcionará:El valor de
this
nunca puede sernull
oundefined
cuando se llama a una función. Cuandonull
oundefined
se suministra como el receptor acall()
oapply()
, el objeto global se usa como el valor para el receptor. Por lo tanto, el código anterior tiene el mismo efecto secundario no deseado de agregar una propiedad nombradavalue
al objeto global.Puede ser útil pensar que una función no tiene conocimiento de la variable a la que está asignada. Esto ayuda a reforzar la idea de que el valor de esto estará vinculado cuando se llama a la función en lugar de cuando se define.
Fin del extracto.
fuente
additionalValues
no se hace referencia dentro delobj.addValues
cuerpovar f = obj.addValues;
se conviertevar f = obj.addValues.bind(obj)
y ahora f (20) funcionaría sin tener que usar call o aplicar cada vez.A veces es útil que un objeto tome prestada la función de otro objeto, lo que significa que el objeto prestatario simplemente ejecuta la función prestada como si fuera la suya.
Un pequeño ejemplo de código:
Estos métodos son muy útiles para dar a los objetos funcionalidad temporal.
fuente
console.log
consulte: ¿Qué es console.log y cómo lo uso?Otro ejemplo con Call, Apply y Bind. La diferencia entre Call y Apply es evidente, pero Bind funciona así:
}
fuente
Me gustaría mostrar un ejemplo, donde se usa el argumento 'valueForThis':
** detalles: http://es5.github.io/#x15.4.4.7 *
fuente
Call () toma argumentos separados por comas, por ejemplo:
.call(scope, arg1, arg2, arg3)
y apply () toma una serie de argumentos, por ejemplo:
.apply(scope, [arg1, arg2, arg3])
Aquí hay algunos ejemplos de uso más: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/
fuente
De los documentos de MDN en Function.prototype.apply () :
De los documentos de MDN en Function.prototype.call () :
Desde Function.apply y Function.call en JavaScript :
Ejemplo de código:
Ver también este violín .
fuente
La diferencia fundamental es que
call()
acepta una lista de argumentos , mientras queapply()
acepta una sola matriz de argumentos .fuente
Aquí hay una publicación pequeña, escribí sobre esto:
http://sizeableidea.com/call-versus-apply-javascript/
fuente
La diferencia es que
call()
toma los argumentos de la función por separado yapply()
toma los argumentos de la función en una matriz.fuente
Podemos diferenciar los métodos de llamada y aplicación de la siguiente manera
LLAMADA: Una función con argumento proporciona individualmente. Si conoce los argumentos a pasar o no hay argumentos para pasar, puede usar call.
APLICAR: llama a una función con el argumento proporcionado como una matriz. Puede usar apply si no sabe cuántos argumentos pasarán a la función.
Hay una ventaja de usar apply over call, no necesitamos cambiar el número de argumentos solo podemos cambiar una matriz que se pasa.
No hay gran diferencia en el rendimiento. Pero podemos decir que la llamada es un poco más rápida en comparación con la aplicación porque una matriz necesita evaluar en el método de aplicación.
fuente
La diferencia entre estos métodos es la forma en que desea pasar los parámetros.
"A para matriz y C para coma" es una práctica mnemónica.
fuente
Llamar y aplicar ambos se utilizan para forzar el
this
valor cuando se ejecuta una función. La única diferencia es quecall
toman+1
argumentos donde 1 esthis
y'n' arguments
.apply
toma solo dos argumentos, uno esthis
el otro es una matriz de argumentos.La ventaja que veo
apply
más arribacall
es que podemos delegar fácilmente una llamada a otra función sin mucho esfuerzo;Observar la facilidad con que delegamos
hello
asayHello
usarapply
, pero concall
esto es muy difícil de lograr.fuente
Aunque
call
yapply
logre lo mismo, creo que hay al menos un lugar donde no se puede usar,call
pero solo se puede usarapply
. Es entonces cuando desea admitir la herencia y desea llamar al constructor.Aquí hay una función que le permite crear clases que también admite la creación de clases extendiendo otras clases.
fuente
Resumen:
Ambos
call()
yapply()
son métodos que se encuentran enFunction.prototype
. Por lo tanto, están disponibles en cada objeto de función a través de la cadena de prototipo. Amboscall()
yapply()
pueden ejecutar una función con un valor especificado dethis
.La principal diferencia entre
call()
yapply()
es la forma en que tienes que pasarle argumentos. En amboscall()
yapply()
pasa como primer argumento el objeto que desea que sea el valorthis
. Los otros argumentos difieren de la siguiente manera:call()
usted tiene que poner los argumentos normalmente (a partir del segundo argumento)apply()
usted tiene que pasar en una variedad de argumentos.Ejemplo:
¿Por qué necesitaría usar estas funciones?
El
this
valor puede ser complicado a veces en javascript. El valor dethis
determinado cuando se ejecuta una función, no cuando se define una función. Si nuestra función depende de unthis
enlace correcto , podemos usarcall()
yapply()
hacer cumplir este comportamiento. Por ejemplo:fuente
La principal diferencia es que, usando call, podemos cambiar el alcance y pasar argumentos de manera normal, pero aplicar le permite llamarlo usando argumentos como una matriz (pasarlos como una matriz). Pero en términos de lo que deben hacer en su código, son bastante similares.
Como puede ver, no hay una gran diferencia, pero aún así, hay casos que preferimos usar call () o apply (). Por ejemplo, mire el código a continuación, que busca el número más pequeño y más grande en una matriz de MDN, utilizando el método de aplicación:
Entonces, la principal diferencia es la forma en que pasamos los argumentos:
Llamada:
Aplicar:
fuente
Permítanme agregar un pequeño detalle a esto.
Estas dos llamadas son casi equivalentes:
Solo hay una pequeña diferencia:
Entonces, estas llamadas se complementan entre sí. Donde esperamos un iterables ,
call
obras, donde se espera una matriz similar ,apply
obras.Y para los objetos que son a la vez iterable y gama-como , como un conjunto de bienes, que técnicamente podríamos utilizar cualquiera de ellos, pero aplicable será probablemente más rápido porque la mayoría de los motores de JavaScript internamente optimizar mejor.
fuente