¿Cuál es la diferencia entre una llamada y una aplicación?

¿Cuál es la diferencia entre usar call y apply para llamar a una función?

 var func = function() { alert('hello!'); }; 

func.apply(); vs func.call();

¿Hay diferencias de rendimiento entre los dos métodos anteriores? ¿Cuándo es mejor usar call over apply y viceversa?

2834
31 дек. fijado por John Duff el 31 de diciembre 2009-12-31 22:56 '10 a las 10:56 pm 2009-12-31 22:56
@ 20 respuestas

La diferencia es que la apply permite llamar a una función con arguments como una matriz; call requiere que los parámetros se enumeren explícitamente. Útil mnemotécnico " A para un rray y C para c omma".

Consulte la documentación de MDN para aplicar y llamar .

Pseudo-sintaxis:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

También existe, con ES6, la capacidad de spread matriz para usar con la función de call , puede ver la compatibilidad aquí .

Ejemplo de código:

3398
31 дек. La respuesta se da plana el 31 de diciembre. 2009-12-31 23:00 '10 a las 23:00 2009-12-31 23:00

K. Scott Allen es una buena entrada en esto.

Básicamente, difieren en cómo manejan los argumentos de la función.

El método apply () es idéntico a calling (), excepto que apply () requiere que se use una matriz como segundo parámetro. La matriz representa los argumentos para el método de destino.

Entonces

 // assuming you have f function f(message) { ... } f.call(receiver, "test"); f.apply(receiver, ["test"]); 
214
31 дек. La respuesta se da nonop 31 dic. 2009-12-31 22:59 '10 a las 10:59 pm 2009-12-31 22:59

Para responder a la pregunta de cuándo usar cada función, use apply si no conoce la cantidad de argumentos que pasará, o si ya están en una matriz o en un objeto similar a una matriz (por ejemplo, t21> objeto para enviar sus propios argumentos. Uso call otra manera, ya que no hay necesidad de envolver los argumentos en una matriz.

 f.call(thisObject, a, b, c); // Fixed number of arguments f.apply(thisObject, arguments); // Forward this function arguments var args = []; while (...) { args.push(some_value()); } f.apply(thisObject, args); // Unknown number of arguments 

Cuando no paso ningún argumento (por ejemplo, su ejemplo), prefiero call , ya que llamo a la función. apply significa que aplica una función a argumentos (no existentes).

No debe haber diferencias en el rendimiento, excepto que tal vez si usa apply y terminar los argumentos en la matriz (por ejemplo, f.apply(thisObject, [a, b, c]) lugar de f.call(thisObject, a, b, c) ). No lo he probado, por lo que puede haber diferencias, pero sería muy específico para el navegador. Probablemente call más rápido si no tiene ningún argumento en la matriz, y apply más rápido si hace esto.

151
01 янв. respuesta dada por Matthew Crumley 01 de enero 2010-01-01 00:50 '10 a las 0:50 2010-01-01 00:50

Aquí hay una buena mnemotécnica. A pply usa A rrays y A siempre toma uno o dos argumentos. Cuando use C, todo lo que necesita es C , especifique el número de argumentos.

103
04 сент. La respuesta se da Joe 04 sep. 2013-09-04 16:36 '13 a las 16:36 2013-09-04 16:36

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 decir exactamente por qué.

Consulte 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 en el rendimiento ... http://youtu.be/ya4UHuXNygM?t=15m52s

Aplicar toma una serie de argumentos, mientras que ¡Llamada toma cero o más parámetros separados! Ah ha

.apply(this, [...])

.call(this, param1, param2, param3, param4...)

91
07 нояб. La respuesta se da kmatheny 07 nov. 2011-11-07 20:36 '11 a las 20:36 2011-11-07 20:36

El siguiente es un extracto del libro "Closing: The Complete Guide" de Michael Bolin . Puede parecer un poco largo, pero infunde mucha información. Del "Apéndice B. Conceptos de JavaScript que a menudo se malinterpretan":


A qué se refiere this cuando se llama la función

Cuando se llama a una función de la forma foo.bar.baz() objeto foo.bar se llama receptor. Cuando se llama a la función, es el receptor, que se utiliza como valor para this :

 var obj = {}; obj.value = 10;  obj.addValues = function(additionalValues) { for (var i = 0; i < arguments.length; i++) { this.value += arguments[i]; } return this.value; }; // Evaluates to 30 because obj is used as the value for 'this' when // obj.addValues() is called, so obj.value becomes 10 + 20. obj.addValues(20); 

Si no hay un destinatario explícito cuando se llama a la función, el objeto global se convierte en el destinatario. Como se explica en "goog.global" en la página 47, una ventana es un objeto global cuando JavaScript se ejecuta en un navegador web. Esto conduce a un comportamiento inesperado:

 var f = obj.addValues; // Evaluates to NaN because window is used as the value for 'this' when // f() is called. Because and window.value is undefined, adding a number to // it results in NaN. f(20); // This also has the unintentional side effect of adding a value to window: alert(window.value); // Alerts NaN 

Aunque obj.addValues y f refieren a la misma función, se comportan de manera diferente cuando se les llama, porque el valor del destinatario difiere con cada llamada. Por esta razón, al llamar a una función que hace referencia a this , es importante asegurarse de que tendrá el valor correcto al llamar. Para mayor claridad, si this no fuera referenciado en el cuerpo de la función, entonces el comportamiento de f(20) y obj.addValues(20) sería el mismo.

Dado que las funciones son objetos de primera clase en JavaScript, pueden tener sus propios métodos. Todas las funciones tienen métodos de call() y apply() que le permiten anular el destinatario (es decir, el Objeto al que se refiere) cuando se llama a la función. Las firmas del método son las siguientes:

  Function.prototype.call;  Function.prototype.apply; 

Tenga en cuenta que la única diferencia entre call() y apply() es que call() toma los parámetros de la función como argumentos separados, mientras que apply() obtiene como una matriz:

 // When f is called with obj as its receiver, it behaves the same as calling // obj.addValues(). Both of the following increase obj.value by 60: f.call(obj, 10, 20, 30); f.apply(obj, [10, 20, 30]); 

Las siguientes llamadas son equivalentes, ya que f y obj.addValues refieren a la misma función:

 obj.addValues.call(obj, 10, 20, 30); obj.addValues.apply(obj, [10, 20, 30]); 

Sin embargo, dado que ni call() ni apply() utilizan el valor de su propio destinatario para reemplazar el argumento del destinatario cuando no se especifica, lo siguiente no funcionará:

 // Both statements evaluate to NaN obj.addValues.call(undefined, 10, 20, 30); obj.addValues.apply(undefined, [10, 20, 30]); 

Este valor nunca puede ser null o undefined al llamar a una función. Cuando un objeto global se utiliza como destinatario para call() o apply() null o undefined . Por lo tanto, el código anterior tiene el mismo efecto secundario indeseable que agregar una propiedad denominada value 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 se conectará cuando se llame a la función, y no cuando se defina.


El final de la declaración.

74
04 дек. La respuesta es dada por Dominykas Mostauskis 04 dic. 2013-12-04 15:41 '13 a las 15:41 2013-12-04 15:41

A veces es útil que una entidad tome prestada la función de otra entidad, lo que significa que la entidad prestataria simplemente realiza la función de proporcionar un préstamo, como si fuera la suya propia.

Un ejemplo de un pequeño código:

 var friend = { car: false, lendCar: function ( canLend ){ this.car = canLend; } }; var me = { car: false, gotCar: function(){ return this.car === true; } }; console.log(me.gotCar()); // false friend.lendCar.call(me, true); console.log(me.gotCar()); // true friend.lendCar.apply(me, [false]); console.log(me.gotCar()); // false 

Estos métodos son muy útiles para proporcionar objetos temporales a los objetos.

33
25 февр. la respuesta es dada tjacks3 25 feb. 2014-02-25 22:31 '14 a las 10:31 pm 2014-02-25 22:31

Otro ejemplo es Call, Apply y Bind. La diferencia entre Call y Apply es obvia, pero Bind funciona de la siguiente manera:

  • Bind devuelve una instancia de una función que puede ejecutarse.
  • El primer parámetro es 'esto'
  • El segundo parámetro es una lista de argumentos separados por comas (por ejemplo, Llamada)

}

 function Person(name) { this.name = name; } Person.prototype.getName = function(a,b) { return this.name + " " + a + " " + b; } var reader = new Person('John Smith'); reader.getName = function() { // Apply and Call executes the function and returns value // Also notice the different ways of extracting 'getName' prototype var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]); console.log("Apply: " + baseName); var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); console.log("Call: " + baseName); // Bind returns function which can be invoked var baseName = Person.prototype.getName.bind(this, "is a", "boy"); console.log("Bind: " + baseName()); } reader.getName();  
24
31 марта '15 в 10:32 2015-03-31 10:32 La respuesta se da Mahesh 31 de marzo de 2015 a las 10:32 2015-03-31 10:32

Me gustaría mostrar un ejemplo donde se usa el argumento valueForThis:

 Array.prototype.push = function(element) {  } var array = []; array.push(1); array.push.apply(array,[2,3]); Array.prototype.push.apply(array,[4,5]); array.push.call(array,6,7); Array.prototype.push.call(array,8,9); //[1, 2, 3, 4, 5, 6, 7, 8, 9] 

** más información: http://es5.github.io/#x15.4.4.7 *

22
05 июля '13 в 13:56 2013-07-05 13:56 la respuesta la ofrece user669677 05 de julio de 2013 a las 13:56 2013-07-05 13:56

Call () acepta argumentos ex delimitados por comas:

.call(scope, arg1, arg2, arg3)

y apply () toma una matriz de argumentos, por ejemplo:

.apply(scope, [arg1, arg2, arg3])

Aquí hay algunos ejemplos de uso: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

20
21 янв. Respuesta dada por Mark Karwowski el 21 de enero. 2014-01-21 21:11 '14 a las 21:11 2014-01-21 21:11

De los documentos MDN a Function.prototype.apply () :

El método apply () llama a una función con el valor dado y los argumentos proporcionados como una matriz (o un objeto similar a una matriz).

Sintaxis

 fun.apply(thisArg, [argsArray]) 

De los documentos MDN a Function.prototype.call () :

El método call () llama a una función con el valor dado y los argumentos proporcionados individualmente.

Sintaxis

 fun.call(thisArg[, arg1[, arg2[, ...]]]) 

Desde Function.apply y Function.call en JavaScript :

El método apply () es idéntico a calling (), excepto que apply () requiere una matriz como segundo parámetro. La matriz representa los argumentos para el método de destino.


Ejemplo de código:

este script . 

18
18 янв. Respuesta dada por John Slegers el 18 de enero. 2016-01-18 05:27 '16 a las 5:27 am 2016-01-18 05:27

La principal diferencia es que call() toma una lista de argumentos. , y apply() toma una matriz de argumentos .

11
28 февр. La respuesta la da Rakesh Kumar el 28 de febrero. 2014-02-28 07:57 '14 a las 7:57 2014-02-28 07:57

Aquí hay un pequeño post, escribí sobre esto:

http://sizeableidea.com/call-versus-apply-javascript/

 var obj1 = { which : "obj1" }, obj2 = { which : "obj2" }; function execute(arg1, arg2){ console.log(this.which, arg1, arg2); } //using call execute.call(obj1, "dan", "stanhope"); //output: obj1 dan stanhope //using apply execute.apply(obj2, ["dan", "stanhope"]); //output: obj2 dan stanhope //using old school execute("dan", "stanhope"); //output: undefined "dan" "stanhope" 
10
04 дек. La respuesta se da Dan 04 dec. 2013-12-04 16:58 '13 a las 16:58 2013-12-04 16:58

La diferencia es que call() toma los argumentos de la función por separado, y apply() toma los argumentos de la función en la matriz.

7
11 авг. Respuesta dada por Sanjib Debnath el 11 de agosto. 2016-08-11 12:25 '16 a las 12:25 2016-08-11 12:25

Podemos diferenciar los métodos de llamar y solicitar, como se muestra a continuación.

LLAMADA: Una función con un argumento se proporciona individualmente. Si conoce los argumentos que deben pasarse o no los argumentos para aprobar, puede utilizar la llamada.

APLICAR: llamada de función con un argumento representado como una matriz. Puede usar aplicar si no sabe cuántos argumentos se pasarán a la función.

Hay una ventaja de usar la aplicación de llamada en exceso, no necesitamos cambiar el número de argumentos, podemos cambiar la matriz transmitida.

No hay gran diferencia en el rendimiento. Pero podemos decir que llamar un poco es más rápido que comparar, porque la matriz debe evaluarse en el método de aplicación.

6
06 нояб. La respuesta se da Praveen D 06 Nov. 2013-11-06 14:50 '13 a las 14:50 2013-11-06 14:50

La diferencia entre estos métodos es cómo desea pasar los parámetros.

"A para array y C para coma" es un mnemotécnico conveniente.

5
03 авг. la respuesta es dada por venkat7668 03 ago. 2015-08-03 09:15 '15 a las 9:15 a.m. 2015-08-03 09:15

Llamar y usar ambos se usa para forzar this valor cuando se ejecuta la función. La única diferencia es que la call toma los argumentos n+1 , donde 1 es this y 'n' arguments . apply solo toma dos argumentos, uno es this , el otro es una matriz de argumentos.

La ventaja que veo en la apply sobre call es que podemos delegar fácilmente una llamada de función a otra función sin mucho esfuerzo;

 function sayHello() { console.log(this, arguments); } function hello() { sayHello.apply(this, arguments); } var obj = {name: 'my name'} hello.call(obj, 'some', 'arguments'); 

Fíjate en lo fácil que es delegar hello para sayHello usando apply , pero con call es muy difícil de lograr.

5
24 нояб. La respuesta la da Raghavendra el 24 de noviembre. 2015-11-24 11:36 '15 a las 11:36 2015-11-24 11:36

Incluso si la call y la apply logran lo mismo, creo que al menos un lugar donde no se puede usar la call , pero solo se puede apply . Esto es cuando desea admitir la herencia y desea llamar a un constructor.

Aquí hay una función que le permite crear clases que también admiten la creación de clases extendiendo otras clases.

 function makeClass( properties ) { var ctor = properties['constructor'] || function(){} var Super = properties['extends']; var Class = function () { // Here 'call' cannot work, only 'apply' can!!! if(Super) Super.apply(this,arguments); ctor.apply(this,arguments); } if(Super){ Class.prototype = Object.create( Super.prototype ); Class.prototype.constructor = Class; } Object.keys(properties).forEach( function(prop) { if(prop!=='constructor'  prop!=='extends') Class.prototype[prop] = properties[prop]; }); return Class; } //Usage var Car = makeClass({ constructor: function(name){ this.name=name; }, yourName: function() { return this.name; } }); //We have a Car class now var carInstance=new Car('Fiat'); carInstance.youName();// ReturnsFiat var SuperCar = makeClass({ constructor: function(ignore,power){ this.power=power; }, extends:Car, yourPower: function() { return this.power; } }); //We have a SuperCar class now, which is subclass of Car var superCar=new SuperCar('BMW xy',2.6); superCar.yourName();//Returns BMW xy superCar.yourPower();// Returns 2.6 
4
12 февр. La respuesta es dada por Dhana Krishnasamy el 12 de febrero. 2015-02-12 21:10 '15 a las 21:10 2015-02-12 21:10

La principal diferencia es que con la ayuda de la llamada podemos cambiar el área y pasar los argumentos como de costumbre, pero aplicar le permite llamarlo usando los argumentos como una matriz (páselos como una matriz). Pero en términos de lo que deberían hacer en su código, son bastante similares.

Aunque la sintaxis de esta función es casi idéntica a la sintaxis del método apply (), la diferencia fundamental es que call () toma una lista de argumentos, y apply () toma una matriz de argumentos.

Entonces, como puede ver, no hay mucha diferencia, pero aún hay casos en los que preferimos usar call () o apply (). Por ejemplo, mire el código a continuación que encuentra el número más pequeño y más grande en una matriz de MDN usando el método de aplicación:

 // min/max number in an array var numbers = [5, 6, 2, 3, 7]; // using Math.min/Math.max apply var max = Math.max.apply(null, numbers); // This about equal to Math.max(numbers[0], ...) // or Math.max(5, 6, ...) var min = Math.min.apply(null, numbers) 

Por lo tanto, la principal diferencia radica en cómo pasamos los argumentos:

Llamada

 function.call(thisArg, arg1, arg2, ...); 

Aplicar:

 function.apply(thisArg, [argsArray]); 
3
11 мая '17 в 17:35 2017-05-11 17:35 Alireza dio la respuesta el 11 de mayo de '17 a las 17:35 2017-05-11 17:35

Resumen:

Tanto call() como apply() son métodos que se encuentran en Function.prototype . Por lo tanto, están disponibles para cada objeto de función a través de una cadena de prototipos. Tanto call() como apply() pueden realizar la función con this valor especificado.

La principal diferencia entre call() y apply() es la forma en que se le pasan los argumentos. Tanto en call() como en apply() usted pasa como primer argumento el objeto que desea que sea un valor, como this . Otros argumentos difieren de la siguiente manera:

  • Con call() debe ingresar argumentos como de costumbre (a partir del segundo argumento)
  • Con apply() debe pasar una matriz de argumentos.

Ejemplo:

 var name = 'unwantedGlobalName'; const obj = { name: 'Willem', sayName () { console.log(this.name);} } let copiedMethod = obj.sayName; // we store the function in the copiedmethod variable copiedMethod(); // this is now window, unwantedGlobalName gets logged copiedMethod.call(obj); // we enforce this to be obj, Willem gets logged 
2
29 авг. La respuesta la da Willem van der Veen el 29 de agosto. 2018-08-29 18:29 '18 a las 6:29 pm 2018-08-29 18:29