Jaka jest różnica między używaniem call
a apply
wywoł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ć call
na apply
odwrót?
javascript
performance
function
dynamic
John Duff
źródło
źródło
a
w przypadku ubiegania się o tablicę argów ic
wzywając do kolumn arg.fn(...input)
wejściem jest tablica. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Odpowiedzi:
Różnica polega na tym, że
apply
możesz wywołać funkcję zarguments
tablicą;call
wymaga 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ść
spread
tablicy do stosowania zcall
funkcji można zobaczyć zgodnoĹ tutaj .Przykładowy kod:
źródło
[]
nazywa się tablicą ,{}
nazywa się obiektem .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.call
iapply
przyjmuje dwa parametry. Pierwszym argumentemapply' and
funkcji call` musi być obiekt właściciela, a drugim parametrem będą odpowiednio parametry oddzielone tablicą lub przecinkami. Jeśli zdasznull
lubundefined
jako pierwszy argument, to w trybie nieściągalnym zostaną one zastąpione obiektem globalnym, tj.window
K. Scott Allen ma fajny artykuł na ten temat.
Zasadniczo różnią się sposobem obsługi argumentów funkcji.
Więc:
źródło
call
ale jest wymaganyapply
Aby odpowiedzieć na pytanie, kiedy użyć każdej funkcji, użyj,
apply
jeśli nie znasz liczby argumentów, które przekażesz, lub jeśli są one już w tablicy lub obiekcie podobnym do tablicy (np.arguments
Obiekt do przekazywania własnych argumentów. Użyjcall
inaczej, ponieważ nie ma potrzeby zawijania argumentów w tablicy.Kiedy nie przekazuję żadnych argumentów (jak twój przykład), wolę,
call
ponieważ wywołuję funkcję.apply
Oznaczałoby jesteś zastosowaniu funkcji do (nieistniejących) argumentów.Nie powinno być żadnych różnic w wydajności, chyba że użyjesz
apply
argumentów i zapakujesz je w tablicę (np.f.apply(thisObject, [a, b, c])
Zamiastf.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. Prawdopodobniecall
jest to szybsze, jeśli nie masz już argumentów w tablicy, iapply
jest szybsze, jeśli tak.źródło
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.
źródło
apply
są wymagane. Nie jestem jednak pewien, dlaczego zadzwonimyapply
lubcall
bez parametru. Wygląda na to, że ktoś próbuje dowiedzieć się, dlaczego tutaj stackoverflow.com/questions/15903782/...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...)
źródło
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
this
dotyczy wywołania funkcjiPodczas wywoływania funkcji formularza
foo.bar.baz()
obiektfoo.bar
nazywany jest odbiorcą. Gdy funkcja jest wywoływana, odbiornik jest używany jako wartość dlathis
: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ń:
Chociaż
obj.addValues
if
odnoszą 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ęthis
ona odnosi , ważne jest, aby upewnić się, żethis
będzie miała poprawną wartość, gdy zostanie wywołana. Dla jasności, gdybythis
nie odwoływać się do treści funkcji, zachowanief(20)
iobj.addValues(20)
byłoby takie samo.Ponieważ funkcje są pierwszorzędnymi obiektami w JavaScript, mogą mieć własne metody. Wszystkie funkcje mają metody
call()
iapply()
które pozwalają na ponowne zdefiniowanie odbiornik (czyli obiekt, którythis
odnosi się do) przy wywołaniu funkcji. Podpisy metod są następujące:Zauważ, że jedyna różnica między
call()
iapply()
polega na tym, żecall()
odbiera parametry funkcji jako poszczególne argumenty, podczas gdyapply()
odbiera je jako pojedynczą tablicę:Następujące wywołania są równoważne
f
iobj.addValues
odnoszą się do tej samej funkcji:Ponieważ jednak ani
call()
nieapply()
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ć:Wartość
this
nigdy nie może byćnull
lubundefined
gdy funkcja jest wywoływana. Gdynull
lubundefined
jest dostarczane jako odbiornik docall()
lubapply()
, 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 nazwievalue
do 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.
źródło
additionalValues
nie odwołuje się wewnątrzobj.addValues
ciałavar 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.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:
Te metody są bardzo przydatne do nadawania obiektom tymczasowej funkcjonalności.
źródło
console.log
sprawdź: Co to jest console.log i jak go używać?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:
}
źródło
Chciałbym pokazać przykład, w którym używany jest argument „valueForThis”:
** szczegóły: http://es5.github.io/#x15.4.4.7 *
źródło
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/
źródło
Z dokumentów MDN na temat Function.prototype.apply () :
Z dokumentacji MDN na temat Function.prototype.call () :
Z Function.apply i Function.call w JavaScript :
Przykład kodu:
Zobacz także to skrzypce .
źródło
Podstawowa różnica polega na tym, że
call()
akceptuje listę argumentów , aapply()
akceptuje pojedynczą tablicę argumentów .źródło
Oto mały post, który napisałem na ten temat:
http://sizeableidea.com/call-versus-apply-javascript/
źródło
Różnica polega na tym,
call()
że argumenty funkcji są oddzielne, aapply()
argumenty funkcji są umieszczane w tablicy.źródło
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.
źródło
Różnica między tymi metodami polega na tym, jak chcesz przekazać parametry.
„A dla tablicy i C dla przecinka” to przydatny mnemonik.
źródło
Wywołaj i zastosuj oba, aby wymusić
this
wartość podczas wykonywania funkcji. Jedyną różnicą jest to, żecall
bierzen+1
argumenty, gdzie 1 jestthis
i'n' arguments
.apply
przyjmuje tylko dwa argumenty, jeden tothis
drugi to tablica argumentów.Zaletą, którą widzę
apply
powyżej,call
jest to, że możemy łatwo delegować wywołanie funkcji do innej funkcji bez większego wysiłku;Obserwować, jak łatwo możemy przekazać
hello
dosayHello
korzystaniaapply
, alecall
jest to bardzo trudne do osiągnięcia.źródło
Mimo tego
call
i osiągnięciaapply
tego samego, myślę, że jest co najmniej jedno miejsce, w którym nie można korzystać,call
ale 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.
źródło
Podsumowanie:
Zarówno
call()
iapply()
są sposoby, które znajdują się naFunction.prototype
. Dlatego są dostępne na każdym obiekcie funkcji za pośrednictwem łańcucha prototypów. Obacall()
iapply()
mogą wykonywać funkcję o określonej wartościthis
.Główną różnicą pomiędzy
call()
iapply()
jest sposób, trzeba przejść w argumenty do niego. W obucall()
iapply()
przekazać jako pierwszy argument obiekt, który ma być jako wartośćthis
. Pozostałe argumenty różnią się w następujący sposób:call()
trzeba umieścić w argumentach normalnie (począwszy od drugiego argumentu)apply()
musisz przekazać szereg argumentów.Przykład:
Dlaczego miałbym korzystać z tych funkcji?
this
Wartość może być trudne, czasami w języku JavaScript. Wartośćthis
określona, kiedy funkcja jest wykonywana, a nie gdy funkcja jest zdefiniowana. Jeśli nasza funkcja zależy od właściwegothis
powiązania, możemy użyćcall()
iapply()
wymusić to zachowanie. Na przykład:źródło
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.
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:
Główną różnicą jest sposób, w jaki przekazujemy argumenty:
Wywołanie:
Zastosować:
źródło
Pozwól mi dodać do tego trochę szczegółów.
te dwa połączenia są prawie równoważne:
Jest tylko niewielka różnica:
Te połączenia wzajemnie się uzupełniają. Tam, gdzie oczekujemy iterowalności ,
call
działa, gdzie oczekujemy macierzowej ,apply
dział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.
źródło