Czy w JavaScript robi różnicę, gdy wywołuję funkcję z nawiasami?


105

Zauważyłem różnicę podczas wywoływania funkcji z pustymi nawiasami lub bez nawiasów. Nie przekazuję jednak żadnych argumentów do funkcji, więc zastanawiałem się, jaka będzie różnica między:

window.onload = initAll();

i

window.onload = initAll;

Prosimy o wyjaśnienie stojącej za tym zasady.


24
@JS Bangs - tylko w języku angielskim (USA); nie gdzie indziej. Chociaż programiści zwykle nazywają je „nawiasami”, aby uniknąć nieporozumień, w brytyjskim angielskim te zaokrąglone nazywane są po prostu nawiasami. Kwadratowe są nazywane „nawiasami kwadratowymi”. en.wikipedia.org/wiki/Bracket
Rob Levine,

13
tak naprawdę oficjalna nazwa UNICODE to nawias. 0028 ( LEFT PARENTHESIS = otwierający nawias (1.0) i 0029 ) RIGHT PARENTHESIS = zamykający nawias (1.0) - unicode.org/charts/charindex.html#P i co na ten temat ma do powiedzenia Dictionary.com - Dictionary.reference.com/ przeglądaj / PARENTHESIS " Jedna lub obie z pionowych zakrzywionych linii, () ..."

8
Więc to nie jest tylko „amerykański angielski”, to jest międzynarodowa standardowa definicja, ponieważ UNICODE to międzynarodowy standard.

2
@fuzzy - Skąd naprawdę bierzesz swoje fakty? {}nazywane są nawiasami wiewiórkowymi.
Anurag

7
@fuzzy lollipop - Unicode to międzynarodowy standard kodowania znaków jako bajtów, a nie nazewnictwa. Autorzy dokumentu Unicode nie twierdzą, że podana nazwa postaci jest standardem międzynarodowym. To kod kontra znak, który definiują. Ale możesz zauważyć, że odnoszą się one również do [i] jako do nawiasów kwadratowych - (nie tylko do „nawiasów”) i że odnoszą się do wszystkich [, {i (jako znaków w nawiasach]. Powinieneś starać się zrozumieć niuanse w drodze różnych miejsc używać tych samych słów Bardzo ważne, jeśli są częścią międzynarodowego zespołu..
Rob Levine

Odpowiedzi:


161
window.onload = initAll();

To jest wykonywane initAll() od razu i przypisuje wartość zwracaną funkcji do window.onload. To zwykle jest nie to, co chcesz. initAll()musiałby zwrócić funkcję, aby miało to sens.

window.onload = initAll;

to przypisuje rzeczywistą funkcję do window.onload- jest to możliwe, ponieważ w JavaScript, jak mówi @Felix, funkcje są obiektami pierwszej klasy - bez jej wykonywania. initAllzostanie wykonana przez zdarzenie load.


18
Należy tu wspomnieć, że funkcje są obiektami pierwszej klasy w JavaScript.
Felix Kling

136

To, co mówi Pekka, jest poprawne, ale chciałbym trochę rozwinąć przykład z przykładem, który pomoże wyjaśnić komuś, kto nie w pełni rozumie wskaźniki funkcji lub delegatów.

Nie użyję, window.onloadponieważ jest to trochę wymyślone, aby pokazać. Zamiast tego użyję prostej funkcji mnożenia do demonstracji:

function Multiply(operator, operand) {
    return operator * operand;
}

Można to również napisać:

Multiply = function(operator, operand) {
    return operator * operand;
}

Podczas gdy w pierwszym przykładzie implikacja może nie być oczywista, w drugim przykładzie wyraźniej widać, że przypisujemy funkcję, która ma 2 parametry do zmiennej o nazwie Multiply, a koncepcja funkcji jako przypisań jest powszechna w całym JavaScript. To mały dowód na to, że funkcje są „obywatelami pierwszej kategorii” , to znaczy można je przekazywać dokładnie tak, jakbyśmy przekazywali wartości.

A teraz do różnicy przydziału:

var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);

W momencie definiowania zmiennej ret Multiplyzostaje wykonana i przypisana wartość zwracana - retstaje się równa 12.

Spróbujmy jeszcze raz w inny sposób:

var operator = 3;
var operand = 4;
var ret = Multiply;

Teraz, w momencie definiowania ret, retstaje się twoją Multiplyfunkcją, a nie wynikiem uzyskanym z twojej Multiplyfunkcji. Wywołania do ret()spowodują wykonanie Twojej Multiplyfunkcji i możesz ją wywołać dokładnie tak, jakbyś zadzwonił Multiply(operator, operand):

var out = ret(3, 4);

jest taki sam jak

var out = Multiply(3, 4);

Skutecznie powiedziałeś, że zamierzasz użyć go retjako delegata Multiply(). Dzwoniąc ret, naprawdę odnosimy się do Multiplyfunkcji.

Wracając do twojego window.onload. Pomyśl o tym jako:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

initAll = function() {
    return 12;
}

Jak więc widzisz, window.onloadjest to funkcja jak każda inna funkcja, nie ma w niej nic specjalnego. Możesz przypisać mu wartość, przypisać mu funkcję, anulować ją, jeśli chcesz - chodzi o to, że nie ma nic bardziej specjalnego window.onloadniż twoja własna funkcja. Jedyną nieznaczną różnicą jest to, że jest wywoływany przez okno po załadowaniu. [Zastrzeżenie: tak naprawdę nigdy nie anulowałem funkcji okna zewnętrznego, więc nie jestem pewien, czy spowoduje to negatywne reperkusje. Można mieć nadzieję, że sprawdzą, czy funkcja jest przypisana przed jej wywołaniem, tj if (window.onload) window.onload();.].

Teraz initAll()nazywamy to, o czym mówimy:

window.onload = initAll();

który równie dobrze mógłby powiedzieć:

window.onload = 12;

Ale kiedy mówimy initAllbez nawiasów, tak naprawdę mówimy: chcę zastąpić jakąkolwiek moją funkcję window.onload, nową funkcją - tj. Chcę zastąpić ją moją initAllfunkcją, aby wszelkie wywołania window.onloaduruchamiały moją initAllkod.

Więc:

window.onload = function() {
    //Doing what all good window.onload functions should do...
}

zastępuje się:

window.onload = function() {
    return 12;
}

Więc każde wywołanie window.onloadto wykona twoją initAllfunkcję zamiast tego, co window.onloadbyło pierwotnie. Zastąpiłeś oryginalną funkcję nową funkcją.

W rzeczywistości, mógłby równie napisać:

window.onload = function() {
    //Write all your init code right in here instead of having a separate 
    //initAll function.
}

Innym przykładem, który może pokazać lepiej, jest:

var d = new Date();
var currentTime = d.getTime();

Niezależnie od tego, jaki czas był w tym czasie, djest przypisany currentTime. Świetnie, ale jest to przydatne tylko wtedy, gdy chcemy dowiedzieć się, o której godzinie została wywołana funkcja zawierająca ten kod - tj. W czasie ładowania strony. A co, jeśli chcemy, aby w dowolnym momencie currentTimewywoływano aktualny czas ?

var currentTime = function() {
    var d = new Date();
    return d.getTime();
}

var a = currentTime(); //The current time at the point a is defined...
var b = currentTime;   //b is a functional reference to currentTime...
var c = b(); //The current time when variable c is defined
var d = c; //The current time when variable c was defined

Zauważ, jak wzywamy b()nasze ci dzadania dokładnie tak, jak moglibyśmy to nazwać currentTime()?


Wspaniała odpowiedź!
Shadi Almosri

Hej, co jeśli chcę dodać funkcję, która pobiera argumenty z detektora zdarzeń?
Shemiroth

16

Funkcje w javascript są obywatelami pierwszej klasy i jako takie mogą być przypisane do innych zmiennych lub przekazywane jako argumenty.

Więc kiedy to zrobisz

window.onload = initAll;

Ustawiasz onloadwłaściwość windowobiektu, aby odwoływała się do initAllsamej funkcji.

Kiedy to zrobisz

window.onload = initAll();

Jesteś ustawiając onloadwłaściwość do przechowywania wartości zwracanej z initAll, ponieważ będzie on wykonać w miejscu na tej linii.


10

initAll jest odniesieniem do wartości funkcji i operatora nawiasów kwadratowych dołączonego do nazwy funkcji URUCHAMIA ten obiekt funkcji.

Więc jeśli zrobisz coś takiego

a = initAll

wtedy astanie się to samo, co initAll- na przykład możesz zrobić a()- ale z

a = initAll()

zmienna azwróci wartość wykonywanej initAllfunkcji


8

Spóźniłem się 6 lat, ale wydaje mi się, że można to wytłumaczyć znacznie prościej niż powyższe odpowiedzi.

Oto więc TLDR ; lub lotu ptaka podczas wywoływania funkcji używania i nieużywania ()„s

Weźmy na przykład tę funkcję:

function foo(){
return 123;
}

jeśli logujesz "foo" - bez ()

console.log(foo); 

---outout------
function foo(){
return 123;
}

Nie używając żadnych ()środków do pobrania samej funkcji . Zrobisz to, jeśli chcesz, aby było przekazywane jako wywołanie zwrotne.


jeśli logujesz "foo ()" - z ()

console.log(foo());
-----output-----
 123

Używanie ()po funkcji oznacza wykonanie funkcji i zwrócenie jej wartości .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.