In JavaScript, fa differenza se chiamo una funzione tra parentesi?


105

Ho notato una differenza quando si chiama una funzione con parentesi vuote o senza parentesi. Tuttavia, non sto passando alcun argomento alla funzione, quindi mi sono chiesto quale sarebbe la differenza tra:

window.onload = initAll();

e

window.onload = initAll;

Si prega di spiegare il principio alla base.


24
@JS Bangs - Solo in inglese americano; non altrove. Sebbene i programmatori tendano a chiamarle "parentesi" per evitare confusione, nell'inglese britannico quelle arrotondate sono conosciute semplicemente come parentesi. Quelle quadrate sono note come "parentesi quadre". en.wikipedia.org/wiki/Bracket
Rob Levine

13
su una nota seria, il nome ufficiale UNICODE è Parenthesis. 0028 ( PARENTESI SINISTRA = parentesi aperta (1.0) e 0029 ) PARENTESI DESTRA = parentesi chiusa (1.0) - unicode.org/charts/charindex.html#P e cosa ne dice Dictionary.com - dictionary.reference.com/ sfoglia / PARENTESI "Una o entrambe le linee curve verticali, () ..."

8
Quindi questa non è solo una cosa "inglese americano", è una definizione di standard internazionale perché UNICODE è uno standard internazionale.

2
@fuzzy - Da dove prendi i tuoi dati, sul serio? {}sono chiamate parentesi squirrelly.
Anurag

7
@fuzzy lollipop - Unicode è uno standard internazionale per la codifica dei caratteri come byte, non per la denominazione. Gli autori del documento Unicode non sostengono che il nome di un personaggio sia uno standard internazionale. È il codice contro il carattere che stanno definendo. Tuttavia, potresti notare che si riferiscono a [e] anche come parentesi quadre - (non solo "parentesi"), e che si riferiscono a tutti i [, {e (come caratteri tra parentesi. Dovresti sforzarti di comprendere le sfumature nel modo in cui luoghi diversi usano le stesse parole. Molto importante se fai parte di una squadra internazionale.
Rob Levine

Risposte:


161
window.onload = initAll();

Questo esegue initAll() prova subito e assegna il valore di ritorno della funzione a window.onload. Di solito non è quello che vuoi. initAll()dovrebbe restituire una funzione perché questo abbia senso.

window.onload = initAll;

questo assegna la funzione effettiva a window.onload- questo è possibile perché in JavaScript, come dice @Felix, le funzioni sono oggetti di prima classe - senza eseguirlo. initAllverrà eseguito dall'evento di caricamento.


18
Importante da menzionare qui è che le funzioni sono oggetti di prima classe in JavaScript.
Felix Kling

136

Ciò che dice Pekka è corretto, ma voglio elaborare un po 'con un esempio che aiuterà a spiegare a qualcuno che non comprende appieno i puntatori di funzioni oi delegati.

Non lo userò window.onloadperché è un po 'artificioso per dimostrare. Userò invece una semplice funzione di moltiplicazione per la demo:

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

Questo potrebbe ugualmente essere scritto:

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

Mentre nel primo esempio, l'implicazione potrebbe non essere ovvia, il secondo esempio mostra più chiaramente che stiamo assegnando una funzione che ha 2 parametri a una variabile chiamata Multiply, e questo concetto di funzioni come assegnazioni è comune in JavaScript. Questa è una piccola dimostrazione del fatto che le funzioni sono "cittadini di prima classe" , cioè possono essere trasmesse esattamente come se stessimo trasmettendo valori.

Quindi ora la differenza di assegnazione:

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

Al punto di definire la variabile ret, Multiplyviene eseguita e viene assegnato il valore di ritorno - retdiventa uguale a 12.

Riproviamo in un modo diverso:

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

Ora, al punto di definire ret, retdiventa la tua Multiplyfunzione anziché essere il risultato ottenuto dalla tua Multiplyfunzione. Le chiamate a ret()causeranno l' Multiplyesecuzione della tua funzione e puoi chiamarla esattamente come se avessi chiamato Multiply(operator, operand):

var out = ret(3, 4);

equivale a

var out = Multiply(3, 4);

Hai effettivamente detto che utilizzerai retcome delegato per Multiply(). Quando si chiama ret, ci riferiamo davvero alla Multiplyfunzione.

Torna al tuo window.onload. Pensa a questo come:

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

initAll = function() {
    return 12;
}

Quindi, come puoi vedere, window.onloadè una funzione come qualsiasi altra funzione, non c'è niente di speciale in essa. Puoi assegnargli un valore, assegnargli una funzione, annullarlo se lo desideri: il punto è che non c'è niente di più speciale di window.onloadquanto lo sia sulla tua funzione. L'unica cosa leggermente diversa è che viene chiamato dalla finestra quando viene caricato. [Disclaimer: non ho mai effettivamente annullato le funzioni della finestra, quindi non sono sicuro che ciò causerà ripercussioni negative. Si spera che controllino per vedere se una funzione è assegnata prima di chiamarla cioè if (window.onload) window.onload();].

Ora chiamare initAll()quello che stiamo dicendo è:

window.onload = initAll();

che potrebbe anche dire:

window.onload = 12;

Ma quando diciamo initAllsenza parentesi, quello che stiamo veramente dicendo è: voglio sostituire qualunque sia la mia funzione window.onload, con una nuova funzione - cioè voglio sostituirla con la mia initAllfunzione, in modo che qualsiasi chiamata a window.onloadesegua la mia initAllcodice.

Così:

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

è sostituito con:

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

Quindi qualsiasi chiamata a window.onloadeseguirà la tua initAllfunzione invece di qualunque cosa window.onloadfosse originariamente. Hai sostituito la funzione originale con la tua nuova funzione.

In realtà, si potrebbe ugualmente scrivere:

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

Un altro esempio che può dimostrare meglio è questo:

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

Qualunque sia l'ora in cui dè definita l'ora viene assegnata currentTime. Ottimo, ma è utile solo se vogliamo scoprire a che ora è stata chiamata la funzione contenente quel codice, cioè al momento del caricamento della pagina. E se volessimo l'ora corrente ogni volta che currentTimeviene chiamata?

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

Notate come chiamiamo i b()nostri incarichi ce desattamente come potremmo chiamare currentTime()?


Risposta meravigliosa!
Shadi Almosri

Ehi, cosa succede se voglio aggiungere una funzione che accetta argomenti su un listener di eventi?
Shemiroth

16

Le funzioni in javascript sono cittadini di prima classe e, come tali, possono essere assegnate ad altre variabili o passate come argomenti.

Quindi, quando lo fai

window.onload = initAll;

Stai impostando la onloadproprietà windowdell'oggetto per fare riferimento alla initAllfunzione stessa.

Quando lo fai

window.onload = initAll();

Stai impostando la onloadproprietà per mantenere il valore restituito di initAll, poiché verrà eseguito in posizione su quella riga.


10

initAll è un riferimento al valore di una funzione e l'operatore tra parentesi viene aggiunto al nome della funzione RUNS questo oggetto funzione.

Quindi se fai qualcosa di simile

a = initAll

allora adiventerà lo stesso di initAll- per esempio puoi fare a()- ma con

a = initAll()

la variabile aotterrà il valore di ritorno della initAllfunzione eseguita


8

Sono in ritardo di 6 anni ma sento che questo avrebbe potuto essere spiegato in modo molto più semplice delle risposte precedenti.

Quindi ecco il TLDR ; o vista a volo d'uccello quando si chiama le funzioni che utilizzano e che non utilizzano ()'s

Prendiamo ad esempio questa funzione:

function foo(){
return 123;
}

se accedi "foo" - senza ()

console.log(foo); 

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

Non usare ()mezzi per recuperare la funzione stessa . Lo faresti se desideri che venga trasmesso come richiamata.


se accedi a "foo ()" con ()

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

Usare ()dopo una funzione significa eseguire la funzione e restituirne il valore .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.