J'étudie THREE.js et j'ai remarqué un modèle où les fonctions sont définies comme suit:
var foo = ( function () {
var bar = new Bar();
return function ( ) {
//actual logic using bar from above.
//return result;
};
}());
(Exemple voir méthode raycast ici ).
La variation normale d'une telle méthode ressemblerait à ceci:
var foo = function () {
var bar = new Bar();
//actual logic.
//return result;
};
En comparant la première version à la variation normale , la première semble différer en ce que:
La principale différence est donc que dans la première variante, la barre n'est affectée qu'une seule fois, lors de l'initialisation, tandis que la deuxième variante crée cette variable temporaire à chaque appel.
Ma meilleure estimation de la raison pour laquelle cela est utilisé est qu'il limite le nombre d'instances pour la barre (il n'y en aura qu'une) et économise ainsi la surcharge de gestion de la mémoire.
Mes questions:
Vos hypothèses sont presque correctes. Examinons-les d'abord.
- Il affecte le retour d'une fonction auto-exécutable
Ceci est appelé expression de fonction immédiatement invoquée ou IIFE
- Il définit une variable locale au sein de cette fonction
C'est la manière d'avoir des champs d'objet privés en JavaScript car elle ne fournit pas le mot-clé ou la fonctionnalité private
autrement.
- Il renvoie la fonction réelle contenant la logique qui utilise la variable locale.
Encore une fois, le point principal est que cette variable locale est privée .
Y a-t-il un nom pour ce modèle?
AFAIK vous pouvez appeler ce modèle modèle de module . Citant:
Le modèle de module encapsule la "confidentialité", l'état et l'organisation à l'aide de fermetures. Il fournit un moyen d'envelopper un mélange de méthodes et de variables publiques et privées, en protégeant les pièces contre les fuites dans la portée mondiale et en entrant accidentellement en contact avec l'interface d'un autre développeur. Avec ce modèle, seule une API publique est renvoyée, gardant tout le reste de la fermeture privé.
En comparant ces deux exemples, mes meilleures suppositions sur la raison pour laquelle le premier est utilisé sont:
Mais si vous avez juste besoin de l'objet Vanilla à chaque fois, ce modèle n'ajoutera probablement aucune valeur.
Il limite les coûts d'initialisation de l'objet et garantit en outre que toutes les invocations de fonction utilisent le même objet . Cela permet, par exemple, à l'état d'être stocké dans l'objet pour de futures invocations à utiliser.
Bien qu'il soit possible que cela limite l'utilisation de la mémoire, le GC collecte généralement les objets inutilisés de toute façon, donc ce modèle n'est pas susceptible d'aider beaucoup.
Ce modèle est une forme spécifique de fermeture .
Je ne sais pas si ce modèle a un nom plus correct, mais cela ressemble à un module pour moi, et la raison pour laquelle il est utilisé est à la fois pour encapsuler et pour maintenir l'état.
La fermeture (identifiée par une fonction dans une fonction) garantit que la fonction interne a accès aux variables de la fonction externe.
Dans l'exemple que vous avez donné, la fonction interne est retournée (et affectée à foo
) en exécutant la fonction externe, ce qui signifie que tmpObject
continue de vivre dans la fermeture et de multiples appels à la fonction interne foo()
fonctionnera sur la même instance de tmpObject
.
La principale différence entre votre code et le code Three.js est que dans le code Three.js la variable tmpObject
n'est initialisée qu'une seule fois, puis partagée par chaque appel de la fonction retournée.
Cela serait utile pour conserver un état entre les appels, similaire à la façon dont les variables static
sont utilisées dans les langages de type C.
tmpObject
est une variable privée visible uniquement par la fonction interne.
Il modifie l'utilisation de la mémoire, mais n'est pas conçu pour économiser de la mémoire.
Je voudrais contribuer à ce fil intéressant en étendant le concept du modèle de module révélateur, qui garantit que toutes les méthodes et variables restent privées jusqu'à ce qu'elles soient explicitement exposées.
Dans ce dernier cas, la méthode d'addition serait appelée Calculator.add ();