En JavaScript, cela fait-il une différence si j'appelle une fonction entre parenthèses?


105

J'ai remarqué une différence lors de l'appel d'une fonction avec des parenthèses vides, ou sans aucune parenthèse. Cependant, je ne transmets aucun argument à la fonction, alors je me suis demandé quelle serait la différence entre:

window.onload = initAll();

et

window.onload = initAll;

Veuillez expliquer le principe sous-jacent.


24
@JS Bangs - Uniquement en anglais américain; pas ailleurs. Bien que les programmeurs aient tendance à les appeler «parenthèses» pour éviter toute confusion, en anglais britannique, les arrondis sont simplement connus sous le nom de parenthèses. Les carrés sont appelés «crochets». en.wikipedia.org/wiki/Bracket
Rob Levine

13
sur une note sérieuse, le nom officiel UNICODE est Parenthesis. 0028 ( PARENTHÈSE GAUCHE = parenthèse ouvrante (1.0) et 0029 ) PARENTHÈSE DROITE = parenthèse fermante (1.0) - unicode.org/charts/charindex.html#P et ce que Dictionary.com en dit - dictionary.reference.com/ parcourir / PARENTHESIS "L'une ou les deux lignes courbes verticales, () ..."

8
Donc, ce n'est pas seulement une chose "en anglais américain", c'est une définition standard internationale car UNICODE est une norme internationale.

2
@fuzzy - D'où tirez-vous vos faits, sérieusement? {}sont appelés parenthèses squirrelly.
Anurag le

7
@fuzzy lollipop - Unicode est une norme internationale sur l'encodage des caractères en octets, pas sur la dénomination. Les auteurs du document Unicode ne prétendent pas que le nom donné pour un caractère est une norme internationale. C'est le code par rapport au caractère qu'ils définissent. Mais, vous voudrez peut-être noter qu'ils font également référence à [et] comme des crochets - (pas seulement des "crochets"), et qu'ils font référence à tous les [, {et (en tant que caractères entre crochets. Vous devez vous efforcer de comprendre les nuances. de la façon dont différents endroits utilisent les mêmes mots. Très important si vous faites partie d'une équipe internationale.
Rob Levine

Réponses:


161
window.onload = initAll();

Cela s'exécute initAll() immédiatement et affecte la valeur de retour de la fonction à window.onload. Ce n'est généralement pas ce que vous voulez. initAll()devrait retourner une fonction pour que cela ait un sens.

window.onload = initAll;

cela assigne la fonction réelle à window.onload- c'est possible parce qu'en JavaScript, comme le dit @Felix, les fonctions sont des objets de première classe - sans l'exécuter. initAllsera exécuté par l'événement de chargement.


18
Il est important de mentionner ici que les fonctions sont des objets de première classe en JavaScript.
Felix Kling le

136

Ce que Pekka dit est correct, mais je veux développer un peu avec un exemple qui aidera à expliquer à quelqu'un qui ne comprend pas complètement les pointeurs de fonction ou les délégués.

Je n'utiliserai pas window.onloadparce que c'est un peu artificiel pour le démontrer. Je vais utiliser une simple fonction de multiplication pour faire une démonstration à la place:

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

Cela pourrait également s'écrire:

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

Alors que dans le premier exemple, l'implication n'est peut-être pas évidente, le deuxième exemple montre plus clairement que nous assignons une fonction qui a 2 paramètres à une variable appelée Multiply, et ce concept de fonctions comme affectations est courant dans tout JavaScript. Ceci est une petite démonstration du fait que les fonctions sont des «citoyens de première classe» , c'est-à-dire qu'elles peuvent être transmises exactement comme si nous transmettions des valeurs.

Alors maintenant à la différence d'affectation:

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

Au moment de définir la variable ret, Multiplyest exécuté et la valeur de retour est affectée -ret devient égale à 12.

Essayons à nouveau d'une manière différente:

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

Maintenant, au moment de la définition ret, retdevient votre Multiplyfonction au lieu d'être le résultat obtenu à partir de votre Multiplyfonction. Les appels à ret()entraîneront Multiplyl'exécution de votre fonction et vous pourrez l'appeler exactement comme si vous aviez appelé Multiply(operator, operand):

var out = ret(3, 4);

est le même que

var out = Multiply(3, 4);

Vous avez effectivement dit que vous allez utiliser retcomme délégué pour Multiply(). Lorsque vous appelez ret, nous nous référons vraiment auMultiply fonction.

Revenez à votre window.onload. Considérez cela comme:

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

initAll = function() {
    return 12;
}

Donc, comme vous pouvez le voir, window.onloadest une fonction comme toute autre fonction, il n'y a rien de spécial à ce sujet. Vous pouvez lui attribuer une valeur, lui attribuer une fonction, l'annuler si vous le souhaitez - le fait est qu'il n'y a rien de plus spécial à propos window.onloadde votre propre fonction. La seule chose légèrement différente est qu'elle est appelée par la fenêtre lorsqu'elle est chargée. [Clause de non-responsabilité: je n'ai jamais annulé les fonctions de fenêtre, donc je ne suis pas sûr que cela entraînera des répercussions négatives. On espère qu'ils vérifient si une fonction est affectée avant de l'appeler ieif (window.onload) window.onload(); ].

Maintenant, nous appelons initAll()ce que nous disons:

window.onload = initAll();

ce qui pourrait aussi bien dire:

window.onload = 12;

Mais quand nous disons initAllsans les parenthèses, ce que nous disons vraiment est: je veux remplacer quelle que soit ma fonction window.onload, par une nouvelle fonction - c'est-à-dire que je veux la remplacer par ma initAllfonction, de sorte que tout appel à window.onloadexécute moninitAll code.

Alors:

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

est remplacé par:

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

Donc, tout appel à window.onloadexécutera votre initAllfonction au lieu de quoi que ce soitwindow.onload était à l'origine. Vous avez remplacé la fonction d'origine par votre nouvelle fonction.

En fait, vous pouvez également écrire:

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

Un autre exemple qui peut mieux démontrer est celui-ci:

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

Quelle que soit l'heure à laquelle le moment dest défini, elle est attribuée currentTime. Génial, mais ce n'est utile que si nous voulons savoir à quelle heure la fonction contenant ce code a été appelée - c'est-à-dire au moment du chargement de la page. Et si nous voulons l'heure actuelle à tout moment qui currentTimeest appelé?

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

Remarquez comment nous appelons b()nos cet daffectations exactement comme nous pourrions appeler currentTime()?


Merveilleuse réponse!
Shadi Almosri

Hé, que faire si je veux ajouter une fonction qui prend des arguments sur un écouteur d'événement?
Shemiroth

16

Les fonctions en javascript sont des citoyens de première classe et, en tant que telles, peuvent être affectées à d'autres variables ou transmises comme arguments.

Alors, quand tu fais

window.onload = initAll;

Vous définissez la onloadpropriété de l' windowobjet pour référencer la initAllfonction elle-même.

Quand tu fais

window.onload = initAll();

Vous définissez la onloadpropriété pour qu'elle contienne la valeur de retour de initAll, car elle s'exécutera en place sur cette ligne.


10

initAll est une référence à une valeur de fonction et l'opérateur entre crochets ajouté au nom de la fonction EXÉCUTE cet objet de fonction.

Donc si vous faites quelque chose comme

a = initAll

alors adeviendra le même que initAll- par exemple vous pouvez le faire a()- mais avec

a = initAll()

la variable aobtiendra la valeur de retour de la initAllfonction exécutée


8

J'ai 6 ans de retard mais je pense que cela aurait pu être expliqué beaucoup plus simplement que les réponses ci-dessus.

Voici donc le TLDR ; ou le point de vue des yeux d'oiseau lors de l' appel des fonctions utilisant ou non ()« s

Prenons cette fonction par exemple:

function foo(){
return 123;
}

si vous vous connectez "foo" - sans ()

console.log(foo); 

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

N'utiliser aucun ()moyen pour récupérer la fonction elle-même . Vous feriez cela si vous voulez qu'il soit transmis comme rappel.


si vous vous connectez "foo ()" - avec ()

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

Utiliser ()après une fonction signifie exécuter la fonction et renvoyer sa valeur .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.