Care este diferența între apel și se aplică?

Care este diferența între utilizarea "apel" și "aplică" pentru a invoca o funcție?

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

func.se aplică(); vs func.apel();

Există diferențele de performanță între cele două metode de mai sus? Când este cel mai bine să utilizați "apel" pe "se aplică" și vice-versa?

Comentarii la întrebare (12)
Soluția

Diferența este că "aplică" vă permite să invoce funcția cu `argumente`` ca o matrice; "apel" necesită parametrii fi enumerate în mod explicit. Un util mnemonic este "O pentru orray și C de cmami."

Vezi MDN's documentație pe apply și cerere.

Pseudo sintaxa:

theFunction.aplica(valueForThis, arrayOfArgs)

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

Există, de asemenea, ca de ES6, posibilitatea de a - spread matrice pentru utilizarea cu "apel" funcția, puteți vedea compatibilități aici.

Mostre de cod:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator
Comentarii (12)

K. Scott Allen a a de frumos writeup în această privință.

Practic, ele diferă în funcție de cum se ocupa funcția de argumente.

aplica() metoda este identică cu call(), se aplică, cu excepția() necesită o serie ca cel de-al doilea parametru. Matrice reprezintă argumente pentru metoda țintă."

Deci:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
Comentarii (2)

Pentru a răspunde la o parte când să-l folosească fiecare funcție, utilizați "aplică", dacă nu't știu numărul de argumente va fi in trecere, sau dacă sunt deja într-o matrice sau matrice-ca obiect (cum ar fi "argumente" obiect de a transmite propriile argumente. Utilizarea "apel", în caz contrar, deoarece nu's nu este nevoie să-și încheie argumente într-o matrice.

f.call(thisObject, a, b, c); // Fixed number of arguments

f.apply(thisObject, arguments); // Forward this function's arguments

var args = [];
while (...) {
    args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

Când m-am'm nu trece nici un argument (ca exemplu), eu prefer "apel" de când am'm asteptare funcția. "aplică" ar implica faptul că sunt aplicarea funcția (inexistente) argumente.

Nu ar trebui't fi orice diferențele de performanță, cu excepția, poate, dacă utilizați "se aplică" și înfășurați argumente într-o matrice (ex. f.aplica(thisObject, [a, b, c]) "în loc de" f.apel(thisObject, a, b, c)). Nu am't testat, deci nu ar putea fi diferențe, dar ar fi foarte specifice browser-ului. L's probabil ca "apel" este mai rapid, dacă nu't au deja argumentele într-o matrice și "aplică" este mai rapid dacă o faci.

Comentarii (0)

Aici's un bun mnemonic. Aaplica folosește Arrays și Always nevoie de unul sau două Argumente. Atunci când utilizați Ctot ce trebuie să Ccantitatea numărul de argumente.

Comentarii (2)

În timp ce acest lucru este un subiect vechi, am vrut doar să subliniez faptul că .apelul este ușor mai rapid decât .se aplică. Pot't spune exact de ce.

Vezi jsPerf, http://jsperf.com/test-call-vs-apply/3


[UPDATE!]

Douglas Crockford menționează pe scurt diferența dintre cele două, care ar putea explica diferenta de performanta... http://youtu.be/ya4UHuXNygM?t=15m52s

Aplica ia o serie de argumente, în timp ce Apelul are zero sau mai multe parametrii individuali! Ah hah!

.aplica(asta, [...])

.apel(asta, param1, param2, param3, param4...)

Comentarii (5)

Urmează un extras din Închidere: Ghidul Definitiv de Michael Bolin. S-ar putea arata un pic cam lung, dar's a saturat cu o mulțime de înțelegere. De la "Anexa B. Frecvent Neînțeles JavaScript Concepte":


Ce "asta" se Referă la atunci Când o Funcție se Numește

Atunci când apelați o funcție de forma foo.bar.baz(), obiectul foo.bar este menționată ca receptor. Atunci când funcția este numit, este receptorul, care este folosit ca valoare pentru "asta":

var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
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);

Dacă nu există explicit receptor atunci când o funcție este numit, apoi, obiect global devine receptor. Așa cum sa explicat în "goog.global" de la pagina 47, fereastra este obiect global atunci când JavaScript este executat într-un browser web. Acest lucru duce la un comportament surprinzător:

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

Chiar dacă obj.addValues și " f " se referă la aceeași funcție, ele se comportă diferit atunci când este solicitat deoarece valoarea de receptor este diferit în fiecare apel. Pentru acest motiv, atunci când apelați o funcție care se referă la "asta", este important să se asigure că "această" va avea valoarea corectă atunci când este chemat. Să fie clar, dacă asta nu au fost menționate în corpul funcției, atunci comportamentul de `f(20) " și " obj.addValues(20) ar fi la fel.

Deoarece funcțiile sunt de prima clasa de obiecte în JavaScript, acestea pot avea propriile lor metode. Toate funcțiile au metodele call () " și "se aplică() care face posibilă pentru a redefini receptor (de exemplu, obiectul care "asta" se referă la) atunci când apelarea funcției. Metoda de semnături sunt după cum urmează:

/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;

Rețineți că singura diferenta dintre apelul lui () " și " se aplică()e apel() primește parametrii funcției individuale argumente, întrucât se aplică() primește-le ca o singură matrice:

// 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]);

Următoarele apeluri sunt echivalente, ca f " și " obj.addValues se referă la aceeași funcție:

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

Cu toate acestea, din moment ce nici call () " sau " se aplică() utilizează valoarea de propriul său receptor substitut pentru receptor argument atunci când este specificat, următoarele nu va funcționa:

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

Valoarea de asta nu poate fi null sau "nedefinit" atunci când o funcție este apelată. Când nul sau nedefinit este furnizat ca receptorul să sune () " sau " se aplică()`, la nivel mondial obiect este folosit ca valoare pentru receptor în loc. Prin urmare, codul anterior are același efect secundar nedorit de a adăuga o proprietate numită "valoare" la obiect global.

Poate fi util să se gândească la o funcție ca având cunoștințe de variabile la care este repartizat. Acest lucru vă ajută să consolideze ideea că valoarea va fi obligat atunci când funcția este numit mai degrabă decât atunci când acesta este definit.


Sfârșitul de extract.

Comentarii (2)

Este util uneori pentru un obiect să împrumute funcție de un alt obiect, în sensul că împrumutul obiect execută pur și simplu a împrumutat funcția ca și cum ar fi propriile sale.

Un mic exemplu de cod:

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

Aceste metode sunt foarte utile pentru a da obiecte funcționalitate temporară.

Comentarii (1)

Un alt exemplu cu Apel, se Aplică și se Leagă. Diferența între Apel și se Aplică este evident, dar Bind funcționează ca aceasta:

  1. Leagă returnează un exemplu de o funcție care poate fi executat
  2. Primul Parametru este 'acest'
  3. Al doilea parametru este un separate prin Virgulă lista de argumente (ca Apel)

}

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();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/
Comentarii (0)

Am'd place să arate un exemplu, unde 'valueForThis' argument este folosit:

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(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] 

*detalii: http://es5.github.io/#x15.4.4.7

Comentarii (0)

Apel() ia separate prin virgulă argumente, ex:

.apel(domeniul de aplicare, arg1, arg2, arg3)

și se aplică() ia o serie de argumente, ex:

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

aici sunt câteva exemple de utilizare: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

Comentarii (1)

De MDN docs pe Funcție.prototip.se aplică() :

aplica() metoda solicită o funcție cu un anumit "această" valoare și argumentele oferite ca o matrice (sau o mulțime-ca obiect).

Sintaxa

distracție.aplica(thisArg, [argsArray])

De MDN docs pe Funcție.prototip.apel() :

metoda call() solicită o funcție cu un anumit "această" valoare și argumentele oferite în mod individual.

Sintaxa

distracție.apel(thisArg[, arg1[, arg2[, ...]]])

De Funcția.se aplică și Funcția.apel în JavaScript :

aplica() metoda este identică cu call(), se aplică, cu excepția() necesită o matrice ca al doilea parametru. Matrice reprezintă argumente pentru metoda țintă.


Exemplu de cod :

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

A se vedea, de asemenea, [acest Vioara][4].

Comentarii (0)

Diferența fundamentală este că call() acceptă o lista de argumente, în timp ce se aplică()` acceptă o o singură serie de argumente.

Comentarii (1)

Aici's un mic-ish post, am scris-o pe asta:

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"
Comentarii (1)

Diferența este că call() ia argumentele funcției separat, și se aplică()` are funcția de argumente într-o matrice.

Comentarii (0)

Putem diferenția apel și de a aplica metodele de mai jos

APEL : O funcție cu un argument furnizeze în mod individual. Dacă știți argumente pentru a fi trecut sau nu există niciun argument pentru a trece puteți utiliza call.

Se APLICĂ : a Apela o funcție cu un argument cu condiția ca o matrice. Puteți utiliza aplica, dacă nu't știu câți argument sunt de gând să treacă la funcție.

Există un avantaj al folosind aplica peste apel, nu ne't nevoie pentru a schimba numărul de argument numai noi putem schimba o matrice care este trecut.

Nu este mare diferenta in performanta. Dar putem spune că apelul este puțin mai rapid ca rezervarea să se aplice pentru o serie nevoie pentru a evalua în aplica metoda.

Comentarii (0)

Diferența dintre aceste metode sunt, cum doriți pentru a trece parametrii.

"Pentru o matrice și C pentru virgulă" este o dezvoltăm.

Comentarii (1)

Apel și se aplică ambele sunt folosite pentru a forța "această" valoare atunci când o funcție este executată. Singura diferență este că "apel" ia "n+1" argumente unde 1 este "asta" și &#39;n&#39; argumente. "aplică" durează doar două argumente, unul este "asta" celălalt este un argument matrice.

Avantajul văd în "aplică" peste "apel" este că putem cu ușurință să delege un apel de funcție pentru altă funcție, fără prea mult efort;

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

Observați cât de ușor ne delegate "bună ziua", să sayHello folosind "aplică", dar cu "apel" acest lucru este foarte dificil de realizat.

Comentarii (0)

Chiar dacă "apel" și "aplică" atinge același lucru, cred că există cel puțin un loc în cazul în care nu puteți utiliza "apel", dar poate folosi doar "aplică". Aceasta este atunci când doriți pentru a sprijini moștenire și doriți pentru a apela constructorul.

Aici este o funcție permite crearea de clase care sprijină, de asemenea crearea de clase prin extinderea în alte clase.

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
Comentarii (1)

Principala diferență este, folosind apel, putem schimba domeniul de aplicare și să treacă argumente, ca de obicei, dar se aplică vă permite să apelați folosind argumente ca o Matrice (le trece ca o matrice). Dar în termeni de ceea ce au de-a face în cod, ele sunt destul de similare.

în Timp ce sintaxa acestei funcții este aproape identic cu cel al aplica(), diferența fundamentală este că sun() acceptă un argument listă, în timp ce se aplică() acceptă o singură serie de argumente.

Deci, după cum vedeți, nu există o diferență mare, dar totuși, există cazuri noi preferăm să folosim apel() sau se aplică(). De exemplu, uita-te la codul de mai jos, care găsirea cel mai mic și cel mai mare număr într-o matrice de MDN, folosind aplica metoda:

// 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)

Deci, principala diferență este modul în care vom trece argumentele:

Telefon:

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

Se aplică:

function.apply(thisArg, [argsArray]);
Comentarii (0)

Rezumat:

Ambele call () " și " se aplică() sunt metode care sunt situate pe Funcție.prototip. Prin urmare, acestea sunt disponibile pe fiecare obiect funcție prin lanț prototip. Ambelecall () " și "se aplică()` poate executa o funcție cu o valoare specificată de "asta".

Principala diferenta dintre apelul lui () " și " se aplică()este modul în care trebuie să treacă în argumente în ea. În ambelecall () " și "se aplică()` te trece ca un prim argument un obiect pe care doriți să fie valoarea ca "asta". Alte argumente diferă în următorul mod:

  • Cu sun() trebuie să pună în argumentele în mod normal (începând cu al doilea argument)
  • Cu se aplică() trebuie să treacă în serie de argumente.

Exemplu:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array

console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

De ce aș avea nevoie pentru a utiliza aceste funcții?

La "această" valoare poate fi dificil uneori în javascript. Valoarea de "asta" determinată atunci când o funcție este executat atunci când o funcție este definită. Dacă funcția noastră este dependend pe o dreapta "asta" obligatoriu putem folosi call () " și " se aplică() pentru a pune în aplicare acest comportament. De exemplu:

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
Comentarii (0)