Jaka jest różnica między połączeniem a zastosowaniem?

3101

Jaka jest różnica między używaniem calla applywywoływaniem funkcji?

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

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

Czy istnieją różnice w wydajności między dwiema wyżej wymienionymi metodami? Kiedy najlepiej stosować callna applyodwrót?

John Duff
źródło
726
Pomyśl o tym aw przypadku ubiegania się o tablicę argów i cwzywając do kolumn arg.
Larry Battle
176
@ LarryBattle Robię prawie to samo, ale myślę, że in stosuje się do tablicy ic w przypadku przecinka (tzn. Argumenty oddzielone przecinkami).
Samih,
3
Zgadzam się, że to głupie. Denerwujące jest to, że pytanie to zadaje się podczas wywiadów, ponieważ wpływowy chump dodał je do swojej listy ważnych pytań.
Ringo,
6
Ubiegasz się o pracę raz (jeden argument), dzwonisz do ludzi wiele razy (kilka argumentów). Alternatywa: istnieje wiele gier Call of Duty.
Gras Double
1
Gdy intencją jest wywołanie funkcji variadic z listą wartości argumentów niezależnie od „tej” wartości, należy użyć operatora rozkładania ES6, np. Gdy fn(...input)wejściem jest tablica. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Gajus

Odpowiedzi:

3644

Różnica polega na tym, że applymożesz wywołać funkcję z argumentstablicą; callwymaga jawnego podania parametrów. Przydatny pamięciowy jest „ za pomocą rray i C o c OMMA”.

Zobacz dokumentację MDN dotyczącą ubiegania się i połączenia .

Pseudo składnia:

theFunction.apply(valueForThis, arrayOfArgs)

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

Jest też, jak z ES6, możliwość spreadtablicy do stosowania z callfunkcji można zobaczyć zgodnoĹ tutaj .

Przykładowy kod:

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

płaska
źródło
24
Należy dodać, że argumenty muszą być tablicą numeryczną ([]). Tablice asocjacyjne ({}) nie będą działać.
Kevin Schroeder
325
@KevinSchroeder: W języku javascript []nazywa się tablicą , {}nazywa się obiektem .
Martijn,
89
Często zapominałem, która tablica bierze, a która oczekuje od ciebie listy argumentów. Technika użyłem do zapamiętania jest to, jeśli pierwsza litera rozpoczęciem metodę z następnie pobiera tablicę czyli o pply tablicy
Aziz punjani
16
@SAM Użycie wywołania zamiast normalnego wywołania funkcji ma sens tylko wtedy, gdy trzeba zmienić wartość tego wywołania funkcji. Przykład (konwertujący argument argument-obiekt na tablicę): Array.prototype.slice.call(arguments)lub [].slice.call(arguments). zastosowanie ma sens, jeśli masz argumenty w tablicy, na przykład w funkcji, która wywołuje inną funkcję z (prawie) tymi samymi parametrami. Zalecenie Użyj normalnego wywołania funkcji, funcname(arg1)jeśli to robi, czego potrzebujesz, i zapisz połączenie i zastosuj się do tych specjalnych okazji, kiedy naprawdę ich potrzebujesz.
jakieś
4
@KunalSingh Oba calli applyprzyjmuje dwa parametry. Pierwszym argumentem apply' and funkcji call` musi być obiekt właściciela, a drugim parametrem będą odpowiednio parametry oddzielone tablicą lub przecinkami. Jeśli zdasz nulllub undefinedjako pierwszy argument, to w trybie nieściągalnym zostaną one zastąpione obiektem globalnym, tj.window
AJ Qarshi
229

K. Scott Allen ma fajny artykuł na ten temat.

Zasadniczo różnią się sposobem obsługi argumentów funkcji.

Metoda Apply () jest identyczna z metodą call (), z tym wyjątkiem, że apply () wymaga tablicy jako drugiego parametru. Tablica reprezentuje argumenty dla metody docelowej. ”

Więc:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);
notnoop
źródło
42
drugi parametr apply () i call () jest opcjonalny, nie jest wymagany.
zły kiwi
34
Pierwszy parametr również nie jest wymagany.
Ikrom
@Ikrom, pierwszy parametr nie jest wymagany, callale jest wymagany apply
iamcastelli
160

Aby odpowiedzieć na pytanie, kiedy użyć każdej funkcji, użyj, applyjeśli nie znasz liczby argumentów, które przekażesz, lub jeśli są one już w tablicy lub obiekcie podobnym do tablicy (np. argumentsObiekt do przekazywania własnych argumentów. Użyj callinaczej, ponieważ nie ma potrzeby zawijania argumentów w tablicy.

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

Kiedy nie przekazuję żadnych argumentów (jak twój przykład), wolę, callponieważ wywołuję funkcję. applyOznaczałoby jesteś zastosowaniu funkcji do (nieistniejących) argumentów.

Nie powinno być żadnych różnic w wydajności, chyba że użyjesz applyargumentów i zapakujesz je w tablicę (np. f.apply(thisObject, [a, b, c])Zamiast f.call(thisObject, a, b, c)). Nie testowałem tego, więc mogą występować różnice, ale byłoby to bardzo specyficzne dla przeglądarki. Prawdopodobnie calljest to szybsze, jeśli nie masz już argumentów w tablicy, i applyjest szybsze, jeśli tak.

Matthew Crumley
źródło
111

Oto dobry mnemonik. Strumień używa szeregów A, a linia A bierze jeden lub dwa Argumenty. Podczas korzystania C wszystko musisz C ount liczbę argumentów.

Joe
źródło
2
Przydatne tutaj mnemoniki !. Zmienię „jeden lub dwa argumenty” na „maksymalnie dwa argumenty”, ponieważ ani pierwszy, ani drugi parametr nie applysą wymagane. Nie jestem jednak pewien, dlaczego zadzwonimy applylub callbez parametru. Wygląda na to, że ktoś próbuje dowiedzieć się, dlaczego tutaj stackoverflow.com/questions/15903782/...
dantheta
92

Chociaż jest to stary temat, chciałem tylko zauważyć, że .call jest nieco szybszy niż .apply. Nie mogę ci dokładnie powiedzieć, dlaczego.

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


[ UPDATE!]

Douglas Crockford krótko wspomina o różnicy między nimi, co może pomóc wyjaśnić różnicę w wydajności ... http://youtu.be/ya4UHuXNygM?t=15m52s

Apply przyjmuje tablicę argumentów, a Call przyjmuje zero lub więcej pojedynczych parametrów! Ach ha!

.apply(this, [...])

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

kmatheny
źródło
Zależy to od tego, co funkcja robi z parametrami / tablicą, jeśli nie musi przetwarzać tablicy, czy zajmuje to mniej czasu?
Eric Hodonsky
12
Co ciekawe, nawet bez tablicy połączenie jest nadal znacznie szybsze. jsperf.com/applyvscallvsfn2
Josh Mc
@JoshMc To byłoby bardzo specyficzne dla przeglądarki. W IE 11 aplikuję się dwa razy szybciej niż połączenie.
Vincent McNabb,
1
1. Utworzenie nowej tablicy oznacza, że ​​śmieciarz będzie musiał ją kiedyś wyczyścić. 2. Dostęp do elementów w tablicy za pomocą dereferencji jest mniej wydajny niż bezpośredni dostęp do zmiennej (parametru). (Wierzę, że to właśnie kmatheny rozumiał przez „parsowanie”, co w rzeczywistości jest czymś zupełnie innym.) Ale żaden z moich argumentów nie wyjaśnia jsperf. Musi to być związane z implementacją przez silnik dwóch funkcji, np. Może i tak tworzą pustą tablicę, jeśli żadna nie zostanie przekazana.
joeytwiddle
Dziękujemy za udostępnienie testu i wideo
Gary
76

Następuje fragment z Closure: The Definitive Guide autorstwa Michaela Bolina . Może wydawać się nieco długi, ale jest nasycony dużą ilością wglądu. Z „Dodatku B. Często źle rozumiane pojęcia JavaScript”:


Co thisdotyczy wywołania funkcji

Podczas wywoływania funkcji formularza foo.bar.baz()obiekt foo.barnazywany jest odbiorcą. Gdy funkcja jest wywoływana, odbiornik jest używany jako wartość dla this:

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

Jeśli po wywołaniu funkcji nie ma jawnego odbiornika, wówczas obiekt globalny staje się odbiorcą. Jak wyjaśniono w „goog.global” na stronie 47, okno jest obiektem globalnym, gdy JavaScript jest uruchamiany w przeglądarce internetowej. Prowadzi to do zaskakujących zachowań:

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

Chociaż obj.addValuesi fodnoszą się do tej samej funkcji, zachowują się inaczej, gdy nazywa ponieważ wartość odbiornika jest inna w każdej rozmowie. Z tego powodu przy wywoływaniu funkcji, do której się thisona odnosi , ważne jest, aby upewnić się, że thisbędzie miała poprawną wartość, gdy zostanie wywołana. Dla jasności, gdyby thisnie odwoływać się do treści funkcji, zachowanie f(20)i obj.addValues(20)byłoby takie samo.

Ponieważ funkcje są pierwszorzędnymi obiektami w JavaScript, mogą mieć własne metody. Wszystkie funkcje mają metody call()i apply()które pozwalają na ponowne zdefiniowanie odbiornik (czyli obiekt, który thisodnosi się do) przy wywołaniu funkcji. Podpisy metod są następujące:

/**
* @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;

Zauważ, że jedyna różnica między call()i apply()polega na tym, że call()odbiera parametry funkcji jako poszczególne argumenty, podczas gdy apply()odbiera je jako pojedynczą tablicę:

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

Następujące wywołania są równoważne fi obj.addValuesodnoszą się do tej samej funkcji:

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

Ponieważ jednak ani call()nie apply()używa wartości własnego odbiornika do zastąpienia argumentu odbiorcy, gdy nie jest on określony, następujące działania nie będą działać:

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

Wartość thisnigdy nie może być nulllub undefinedgdy funkcja jest wywoływana. Gdy nulllub undefinedjest dostarczane jako odbiornik do call()lub apply(), zamiast tego używany jest obiekt globalny jako wartość dla odbiornika. Dlatego poprzedni kod ma ten sam niepożądany efekt uboczny dodawania właściwości o nazwie valuedo obiektu globalnego.

Pomocne może być myślenie o funkcji jako nie posiadającej wiedzy o zmiennej, do której jest przypisana. Pomaga to wzmocnić ideę, że wartość tego będzie ograniczona, gdy funkcja zostanie wywołana, a nie kiedy zostanie zdefiniowana.


Koniec wyciągu.

Dominykas Mostauskis
źródło
Wystarczy zwrócić uwagę na fakt, że additionalValuesnie odwołuje się wewnątrz obj.addValuesciała
Wiktor Stolbin
Wiem, że odpowiadałeś na pytanie, ale chciałbyś dodać: mogłeś użyć binda podczas definiowania f. var f = obj.addValues;staje się var f = obj.addValues.bind(obj) i teraz f (20) działałby bez konieczności używania połączenia lub stosowania za każdym razem.
jhliberty,
Wiem, że go nie napisałeś, ale podkreśliłeś tekst i przykłady z książki jako istotne i jestem bardzo wdzięczny. Byli bardzo pomocni.
Fralcon,
34

Czasami przydaje się, aby jeden obiekt pożyczył funkcję innego obiektu, co oznacza, że ​​pożyczony obiekt po prostu wykonuje pożyczoną funkcję, jakby była jej własną.

Mały przykład kodu:

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

Te metody są bardzo przydatne do nadawania obiektom tymczasowej funkcjonalności.

tjacks3
źródło
1
Dla osób, które chcą wiedzieć, jak to zobaczyć, console.logsprawdź: Co to jest console.log i jak go używać?
Michel Ayres,
25

Kolejny przykład z Call, Apply i Bind. Różnica między Call a Apply jest oczywista, ale Bind działa w następujący sposób:

  1. Bind zwraca instancję funkcji, którą można wykonać
  2. Pierwszy parametr to „ to
  3. Drugi parametr to lista argumentów oddzielona przecinkami (np. Call )

}

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
*/
Mahesh
źródło
23

Chciałbym pokazać przykład, w którym używany jest argument „valueForThis”:

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] 

** szczegóły: http://es5.github.io/#x15.4.4.7 *


źródło
20

Call () przyjmuje argumenty rozdzielane przecinkami, np .:

.call(scope, arg1, arg2, arg3)

i apply () przyjmuje tablicę argumentów, np .:

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

oto kilka innych przykładów użycia: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/

Mark Karwowski
źródło
`// call () === argumenty oddzielone przecinkami (lista argumentów) .call (this, args1, args2, args3, ...) // Apply () === tablica argumentów (elementy-tablic). Apply (this, [arr0, arr1, arr2, ...]) `
xgqfrms
19

Z dokumentów MDN na temat Function.prototype.apply () :

Metoda apply () wywołuje funkcję o podanej thiswartości i argumentach podanych jako tablica (lub obiekt podobny do tablicy).

Składnia

fun.apply(thisArg, [argsArray])

Z dokumentacji MDN na temat Function.prototype.call () :

Metoda call () wywołuje funkcję o podanej thiswartości i argumentach podanych indywidualnie.

Składnia

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

Z Function.apply i Function.call w JavaScript :

Metoda Apply () jest identyczna z metodą call (), z tym wyjątkiem, że apply () wymaga tablicy jako drugiego parametru. Tablica reprezentuje argumenty dla metody docelowej.


Przykład kodu:

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'
));

Zobacz także to skrzypce .

John Slegers
źródło
10

Oto mały post, który napisałem na ten temat:

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"
Dan
źródło
tutaj jest inny: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply, ale w zasadzie ma rację: .call (zakres, arg1, arg2, arg3)
Mark Karwowski
7

Różnica polega na tym, call()że argumenty funkcji są oddzielne, a apply()argumenty funkcji są umieszczane w tablicy.

Sanjib Debnath
źródło
6

Możemy rozróżnić metody połączeń i zastosować jak poniżej

WEZWANIE: Funkcja z argumentem zapewnia indywidualnie. Jeśli znasz argumenty do przekazania lub nie ma argumentu do przekazania, możesz użyć wywołania.

ZASTOSUJ: Wywołaj funkcję z argumentem podanym w postaci tablicy. Możesz użyć opcji Zastosuj, jeśli nie wiesz, ile argumentów zostanie przekazanych do funkcji.

Zaletą jest zastosowanie zastosowania w stosunku do wywołania, nie musimy zmieniać liczby argumentów, tylko możemy zmienić przekazywaną tablicę.

Nie ma dużej różnicy w wydajności. Ale możemy powiedzieć, że wywołanie jest nieco szybsze w porównaniu do zastosowania, ponieważ tablica musi ocenić w metodzie zastosowania.

Praveen D.
źródło
5

Różnica między tymi metodami polega na tym, jak chcesz przekazać parametry.

„A dla tablicy i C dla przecinka” to przydatny mnemonik.

venkat7668
źródło
11
Co zawiera ta odpowiedź, która nie jest dobrze opisana w innych odpowiedziach?
Kyll,
5

Wywołaj i zastosuj oba, aby wymusić thiswartość podczas wykonywania funkcji. Jedyną różnicą jest to, że callbierze n+1argumenty, gdzie 1 jest thisi 'n' arguments. applyprzyjmuje tylko dwa argumenty, jeden to thisdrugi to tablica argumentów.

Zaletą, którą widzę applypowyżej, calljest to, że możemy łatwo delegować wywołanie funkcji do innej funkcji bez większego wysiłku;

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

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

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

Obserwować, jak łatwo możemy przekazać hellodo sayHellokorzystania apply, ale calljest to bardzo trudne do osiągnięcia.

Raghavendra
źródło
4

Mimo tego calli osiągnięcia applytego samego, myślę, że jest co najmniej jedno miejsce, w którym nie można korzystać, callale można tylko korzystać apply. Wtedy chcesz wesprzeć dziedziczenie i wywołać konstruktor.

Oto funkcja umożliwiająca tworzenie klas, która obsługuje także tworzenie klas poprzez rozszerzenie innych klas.

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
Dhana Krishnasamy
źródło
Myślę, że połączenie działałoby tam z operatorem rozkładania, jak opisano w wybranej odpowiedzi. Chyba że coś mi umknie.
jhliberty,
4

Podsumowanie:

Zarówno call()i apply()są sposoby, które znajdują się na Function.prototype. Dlatego są dostępne na każdym obiekcie funkcji za pośrednictwem łańcucha prototypów. Oba call()i apply()mogą wykonywać funkcję o określonej wartości this.

Główną różnicą pomiędzy call()i apply()jest sposób, trzeba przejść w argumenty do niego. W obu call()i apply()przekazać jako pierwszy argument obiekt, który ma być jako wartość this. Pozostałe argumenty różnią się w następujący sposób:

  • Ze call()trzeba umieścić w argumentach normalnie (począwszy od drugiego argumentu)
  • Z apply()musisz przekazać szereg argumentów.

Przykład:

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

Dlaczego miałbym korzystać z tych funkcji?

thisWartość może być trudne, czasami w języku JavaScript. Wartość thisokreślona, kiedy funkcja jest wykonywana, a nie gdy funkcja jest zdefiniowana. Jeśli nasza funkcja zależy od właściwego thispowiązania, możemy użyć call()i apply()wymusić to zachowanie. Na przykład:

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

Willem van der Veen
źródło
4

Główna różnica polega na tym, że za pomocą wywołania możemy zmienić zakres i przekazywać argumenty w normalny sposób, ale zastosowanie pozwala na wywołanie go za pomocą argumentów jako tablicy (przekazanie ich jako tablicy). Ale pod względem tego, co mają zrobić w kodzie, są bardzo podobne.

Podczas gdy składnia tej funkcji jest prawie identyczna jak w przypadku apply (), podstawowa różnica polega na tym, że call () akceptuje listę argumentów, podczas gdy apply () akceptuje pojedynczą tablicę argumentów.

Jak widać, nie ma dużej różnicy, ale są przypadki, w których wolimy używać call () lub apply (). Na przykład spójrz na poniższy kod, który znajduje najmniejszą i największą liczbę w tablicy z MDN, stosując metodę Apply:

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

Główną różnicą jest sposób, w jaki przekazujemy argumenty:

Wywołanie:

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

Zastosować:

function.apply(thisArg, [argsArray]);
Alireza
źródło
2

Pozwól mi dodać do tego trochę szczegółów.

te dwa połączenia są prawie równoważne:

func.call(context, ...args); // pass an array as list with spread operator

func.apply(context, args);   // is same as using apply

Jest tylko niewielka różnica:

  • spreadOperator ... umożliwia przepuszczenie iterowalny args jak listy, aby zadzwonić.
  • applyAkceptuje tylko tablicowej argumenty.

Te połączenia wzajemnie się uzupełniają. Tam, gdzie oczekujemy iterowalności , calldziała, gdzie oczekujemy macierzowej , applydziała.

W przypadku obiektów, które są zarówno iterowalne, jak i tablicowe , jak prawdziwa tablica, technicznie moglibyśmy użyć dowolnego z nich, ale zastosowanie będzie prawdopodobnie szybsze, ponieważ większość silników JavaScript lepiej go optymalizuje wewnętrznie.

Pravin Divraniya
źródło