J'ai posé une question sur le curry et les fermetures ont été mentionnées. Qu'est-ce qu'une fermeture? Comment est-ce lié au curry?
432
J'ai posé une question sur le curry et les fermetures ont été mentionnées. Qu'est-ce qu'une fermeture? Comment est-ce lié au curry?
Réponses:
Portée variable
Lorsque vous déclarez une variable locale, cette variable a une portée. Généralement, les variables locales n'existent que dans le bloc ou la fonction dans laquelle vous les déclarez.
Si j'essaie d'accéder à une variable locale, la plupart des langues la rechercheront dans la portée actuelle, puis remonteront dans les portées parent jusqu'à ce qu'elles atteignent la portée racine.
Lorsqu'un bloc ou une fonction est terminé, ses variables locales ne sont plus nécessaires et sont généralement supprimées de la mémoire.
C'est ainsi que nous nous attendons normalement à ce que les choses fonctionnent.
Une fermeture est une portée de variable locale persistante
Une fermeture est une portée persistante qui conserve les variables locales même après que l'exécution du code a quitté ce bloc. Les langages qui prennent en charge la fermeture (tels que JavaScript, Swift et Ruby) vous permettront de conserver une référence à une étendue (y compris ses étendues parentes), même après l'exécution du bloc dans lequel ces variables ont été déclarées, à condition que vous gardiez une référence à ce bloc ou cette fonction quelque part.
L'objet scope et toutes ses variables locales sont liés à la fonction et persisteront tant que cette fonction persistera.
Cela nous donne la portabilité des fonctions. Nous pouvons nous attendre à ce que toutes les variables qui étaient dans la portée lorsque la fonction a été définie pour la première fois soient toujours dans la portée lorsque nous l'appellerons plus tard, même si nous appelons la fonction dans un contexte complètement différent.
Par exemple
Voici un exemple très simple en JavaScript qui illustre le point:
Ici, j'ai défini une fonction au sein d'une fonction. La fonction interne accède à toutes les variables locales de la fonction externe, y compris
a
. La variablea
est dans la portée de la fonction interne.Normalement, lorsqu'une fonction se termine, toutes ses variables locales sont supprimées. Cependant, si nous renvoyons la fonction interne et l'affectons à une variable
fnc
afin qu'elle persiste aprèsouter
sa sortie, toutes les variables qui étaient dans la portée au moment deinner
sa définition persistent également . La variablea
a été fermée au cours - elle est dans une fermeture.Notez que la variable
a
est totalement privée defnc
. C'est un moyen de créer des variables privées dans un langage de programmation fonctionnel tel que JavaScript.Comme vous pourriez le deviner, lorsque j'appelle,
fnc()
il affiche la valeur dea
, qui est "1".Dans un langage sans fermeture, la variable
a
aurait été récupérée et jetée à laouter
sortie de la fonction . L'appel de fnc aurait généré une erreur car ila
n'existe plus.En JavaScript, la variable
a
persiste car la portée de la variable est créée lors de la première déclaration de la fonction et persiste aussi longtemps que la fonction continue d'exister.a
appartient à la portée deouter
. La portée deinner
a un pointeur parent sur la portée deouter
.fnc
est une variable qui pointe versinner
.a
persiste aussi longtemps quefnc
persiste.a
est dans la fermeture.la source
Je vais donner un exemple (en JavaScript):
Ce que fait cette fonction, makeCounter, c'est qu'elle retourne une fonction, que nous avons appelée x, qui comptera de un à chaque fois qu'elle sera appelée. Puisque nous ne fournissons aucun paramètre à x, il doit en quelque sorte se souvenir du nombre. Il sait où le trouver en fonction de ce qu'on appelle la portée lexicale - il doit chercher l'endroit où il est défini pour trouver la valeur. Cette valeur «cachée» est ce qu'on appelle une fermeture.
Voici à nouveau mon exemple de curry:
Ce que vous pouvez voir, c'est que lorsque vous appelez add avec le paramètre a (qui est 3), cette valeur est contenue dans la fermeture de la fonction retournée que nous définissons comme étant add3. De cette façon, lorsque nous appelons add3, il sait où trouver la valeur a pour effectuer l'addition.
la source
La réponse de Kyle est plutôt bonne. Je pense que la seule précision supplémentaire est que la fermeture est essentiellement un instantané de la pile au moment où la fonction lambda est créée. Ensuite, lorsque la fonction est réexécutée, la pile est restaurée à cet état avant d'exécuter la fonction. Ainsi, comme le mentionne Kyle, cette valeur cachée (
count
) est disponible lorsque la fonction lambda s'exécute.la source
Tout d'abord, contrairement à ce que la plupart des gens ici vous disent, la fermeture n'est pas une fonction ! Alors qu'est - est - il?
Il s'agit d'un ensemble de symboles définis dans le "contexte environnant" d'une fonction (connu sous le nom d' environnement ) qui en font une expression CLOSED (c'est-à-dire une expression dans laquelle chaque symbole est défini et a une valeur, de sorte qu'il peut être évalué).
Par exemple, lorsque vous avez une fonction JavaScript:
c'est une expression fermée car tous les symboles qui s'y trouvent y sont définis (leur signification est claire), vous pouvez donc l'évaluer. En d'autres termes, il est autonome .
Mais si vous avez une fonction comme celle-ci:
c'est une expression ouverte parce qu'il contient des symboles qui n'y sont pas définis. A savoir,
y
. En regardant cette fonction, nous ne pouvons pas dire ce qu'elley
est et ce qu'elle signifie, nous ne connaissons pas sa valeur, nous ne pouvons donc pas évaluer cette expression. C'est-à-dire que nous ne pouvons pas appeler cette fonction jusqu'à ce que nous disions ce qu'elley
est censée signifier. C'est cey
qu'on appelle une variable libre .Cela
y
demande une définition, mais cette définition ne fait pas partie de la fonction - elle est définie ailleurs, dans son "contexte environnant" (également connu sous le nom d' environnement ). C'est du moins ce que nous espérons: PPar exemple, il pourrait être défini globalement:
Ou il pourrait être défini dans une fonction qui l'enveloppe:
La partie de l'environnement qui donne aux variables libres dans une expression leur signification est la fermeture . Il est appelé ainsi, car il transforme une expression ouverte en expression fermée , en fournissant ces définitions manquantes pour toutes ses variables libres , afin que nous puissions l'évaluer.
Dans l'exemple ci-dessus, la fonction interne (à laquelle nous n'avons pas donné de nom parce que nous n'en avions pas besoin) est une expression ouverte car la variable
y
qu'elle contient est libre - sa définition est en dehors de la fonction, dans la fonction qui l'enveloppe . L' environnement de cette fonction anonyme est l'ensemble des variables:Maintenant, la fermeture est la partie de cet environnement qui ferme la fonction interne en fournissant les définitions de toutes ses variables libres . Dans notre cas, la seule variable libre dans la fonction interne était
y
, donc la fermeture de cette fonction est ce sous-ensemble de son environnement:Les deux autres symboles définis dans l'environnement ne font pas partie de la fermeture de cette fonction, car elle ne nécessite pas leur exécution. Ils ne sont pas nécessaires pour le fermer .
Plus d'informations sur la théorie derrière cela ici: https://stackoverflow.com/a/36878651/434562
Il convient de noter que dans l'exemple ci-dessus, la fonction wrapper renvoie sa fonction interne sous forme de valeur. Le moment où nous appelons cette fonction peut être éloigné dans le temps à partir du moment où la fonction a été définie (ou créée). En particulier, sa fonction d'habillage n'est plus en cours d'exécution, et ses paramètres qui étaient sur la pile d'appels ne sont plus là: P Cela pose problème, car la fonction interne doit
y
être là quand elle est appelée! En d'autres termes, il nécessite les variables de sa fermeture pour survivre en quelque sorte à la fonction wrapper et être là en cas de besoin. Par conséquent, la fonction interne doit faire un instantané de ces variables qui rendent sa fermeture et les stocker dans un endroit sûr pour une utilisation ultérieure. (Quelque part en dehors de la pile d'appels.)Et c'est pourquoi les gens confondent souvent le terme fermeture comme étant ce type spécial de fonction qui peut faire de tels instantanés des variables externes qu'ils utilisent, ou la structure de données utilisée pour stocker ces variables pour plus tard. Mais j'espère que vous comprenez maintenant qu'il ne s'agit pas de la fermeture elle-même - ce sont juste des moyens d' implémenter des fermetures dans un langage de programmation, ou des mécanismes de langage qui permettent aux variables de la fermeture de la fonction d'être là en cas de besoin. Il y a beaucoup d'idées fausses autour des fermetures qui rendent (inutilement) ce sujet beaucoup plus confus et compliqué qu'il ne l'est réellement.
la source
Une fermeture est une fonction qui peut référencer un état dans une autre fonction. Par exemple, en Python, cela utilise la fermeture "intérieure":
la source
Pour faciliter la compréhension des clôtures, il pourrait être utile d'examiner comment elles pourraient être mises en œuvre dans un langage procédural. Cette explication suivra une implémentation simpliste des fermetures dans Scheme.
Pour commencer, je dois introduire le concept d'espace de noms. Lorsque vous entrez une commande dans un interpréteur Scheme, il doit évaluer les différents symboles dans l'expression et obtenir leur valeur. Exemple:
Les expressions de définition stockent la valeur 3 à l'endroit pour x et la valeur 4 à l'endroit pour y. Ensuite, lorsque nous appelons (+ xy), l'interpréteur recherche les valeurs dans l'espace de noms et est capable d'effectuer l'opération et de retourner 7.
Cependant, dans Scheme, il existe des expressions qui vous permettent de remplacer temporairement la valeur d'un symbole. Voici un exemple:
Le mot clé let introduit un nouvel espace de noms avec x comme valeur 5. Vous remarquerez qu'il peut toujours voir que y est 4, ce qui fait que la somme renvoyée est 9. Vous pouvez également voir qu'une fois l'expression terminée x revient à 3. Dans ce sens, x a été temporairement masqué par la valeur locale.
Les langages procéduraux et orientés objet ont un concept similaire. Chaque fois que vous déclarez une variable dans une fonction qui porte le même nom qu'une variable globale, vous obtenez le même effet.
Comment pourrions-nous mettre cela en œuvre? Une manière simple est avec une liste chaînée - la tête contient la nouvelle valeur et la queue contient l'ancien espace de noms. Lorsque vous devez rechercher un symbole, vous commencez par la tête et descendez la queue.
Passons maintenant à l'implémentation de fonctions de première classe pour le moment. Plus ou moins, une fonction est un ensemble d'instructions à exécuter lorsque la fonction est appelée aboutissant à la valeur de retour. Lorsque nous lisons dans une fonction, nous pouvons stocker ces instructions en arrière-plan et les exécuter lorsque la fonction est appelée.
Nous définissons x pour être 3 et plus-x pour son paramètre, y, plus la valeur de x. Enfin, nous appelons plus-x dans un environnement où x a été masqué par un nouveau x, celui-ci valant 5. Si nous stockons simplement l'opération, (+ xy), pour la fonction plus-x, puisque nous sommes dans le contexte de x étant 5, le résultat renvoyé serait 9. C'est ce qu'on appelle la portée dynamique.
Cependant, Scheme, Common Lisp et de nombreux autres langages ont ce qu'on appelle la portée lexicale - en plus de stocker l'opération (+ xy), nous stockons également l'espace de noms à ce point particulier. De cette façon, lorsque nous recherchons les valeurs, nous pouvons voir que x, dans ce contexte, est vraiment 3. Il s'agit d'une fermeture.
En résumé, nous pouvons utiliser une liste chaînée pour stocker l'état de l'espace de noms au moment de la définition de la fonction, ce qui nous permet d'accéder aux variables à partir des étendues englobantes, ainsi que de nous fournir la possibilité de masquer localement une variable sans affecter le reste de la programme.
la source
Why do we want to access variables that are out of scope? when we say let x = 5, we want x to be 5 and not 3. What is happening?
Voici un exemple concret de la raison pour laquelle les fermetures donnent un coup de pied au cul ... Cela vient tout droit de mon code Javascript. Permettez-moi d'illustrer.
Et voici comment vous l'utiliseriez:
Imaginez maintenant que vous souhaitiez que la lecture démarre différée, comme par exemple 5 secondes plus tard après l'exécution de cet extrait de code.
delay
Et bien c'est facile avec et c'est la fermeture:Lorsque vous appelez
delay
avec5000
ms, le premier extrait s'exécute et stocke les arguments passés dans sa fermeture. Puis, 5 secondes plus tard, lorsque lesetTimeout
rappel se produit, la fermeture conserve toujours ces variables, de sorte qu'elle peut appeler la fonction d'origine avec les paramètres d'origine.Il s'agit d'un type de curry ou d'une décoration fonctionnelle.
Sans fermetures, vous devriez en quelque sorte maintenir l'état de ces variables en dehors de la fonction, jetant ainsi le code en dehors de la fonction avec quelque chose qui appartient logiquement à l'intérieur. L'utilisation de fermetures peut améliorer considérablement la qualité et la lisibilité de votre code.
la source
Les fonctions ne contenant aucune variable libre sont appelées fonctions pures.
Les fonctions contenant une ou plusieurs variables libres sont appelées fermetures.
src: https://leanpub.com/javascriptallongesix/read#leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure
la source
tl; dr
Une fermeture est une fonction et sa portée affectée (ou utilisée comme) une variable. Ainsi, la fermeture du nom: la portée et la fonction sont enfermées et utilisées comme n'importe quelle autre entité.
Explication détaillée du style Wikipedia
Selon Wikipedia, une fermeture est:
Qu'est-ce que ça veut dire? Regardons quelques définitions.
Je vais expliquer les fermetures et autres définitions associées en utilisant cet exemple:
Fonctions de première classe
Fondamentalement, cela signifie que nous pouvons utiliser des fonctions comme n'importe quelle autre entité . Nous pouvons les modifier, les passer comme arguments, les renvoyer des fonctions ou les affecter à des variables. Techniquement parlant, ce sont des citoyens de première classe , d'où le nom: fonctions de première classe.
Dans l'exemple ci-dessus,
startAt
renvoie une fonction ( anonyme ) à laquelle la fonction est affectée àclosure1
etclosure2
. Ainsi, comme vous le voyez, JavaScript traite les fonctions comme toutes les autres entités (citoyens de première classe).Liaison de nom
La liaison de nom consiste à savoir quelles données une variable (identifiant) référence . La portée est vraiment importante ici, car c'est la chose qui déterminera comment une liaison est résolue.
Dans l'exemple ci-dessus:
y
est lié à3
.startAt
la portée de,x
est lié à1
ou5
(selon la fermeture).À l'intérieur de la portée de la fonction anonyme,
x
n'est liée à aucune valeur, elle doit donc être résolue dans unestartAt
portée supérieure ( 's).Cadrage lexical
Comme le dit Wikipedia , la portée:
Il existe deux techniques:
Pour plus d'explications, consultez cette question et jetez un œil à Wikipedia .
Dans l'exemple ci-dessus, nous pouvons voir que JavaScript a une portée lexicale, car lorsqu'il
x
est résolu, la liaison est recherchée dans lastartAt
portée supérieure ( s), en fonction du code source (la fonction anonyme qui recherche x est définie à l'intérieurstartAt
) et pas basé sur la pile d'appels, la façon (la portée où) la fonction a été appelée.Emballage (fermeture) vers le haut
Dans notre exemple, lorsque nous appelons
startAt
, il retournera une fonction (de première classe) qui sera affectéeclosure1
etclosure2
donc une fermeture est créée, car les variables passées1
et5
seront enregistrées dansstartAt
la portée de ', qui seront jointes avec le retour fonction anonyme. Lorsque nous appelons cette fonction anonyme viaclosure1
etclosure2
avec le même argument (3
), la valeur dey
sera trouvée immédiatement (car c'est le paramètre de cette fonction), maisx
n'est pas liée dans la portée de la fonction anonyme, donc la résolution continue dans la portée de fonction supérieure (lexicalement) (qui a été enregistrée dans la fermeture) oùx
se trouve être lié à1
ou5
. Maintenant, nous savons tout pour la sommation afin que le résultat puisse être retourné, puis imprimé.Vous devez maintenant comprendre les fermetures et leur comportement, ce qui est un élément fondamental de JavaScript.
Currying
Oh, et vous avez également appris ce qu'est le curry : vous utilisez des fonctions (fermetures) pour passer chaque argument d'une opération au lieu d'utiliser une fonction avec plusieurs paramètres.
la source
La fermeture est une fonctionnalité en JavaScript où une fonction a accès à ses propres variables de portée, accès aux variables de fonction externes et accès aux variables globales.
La fermeture a accès à sa portée de fonction externe même après le retour de la fonction externe. Cela signifie qu'une fermeture peut mémoriser et accéder aux variables et arguments de sa fonction externe même après la fin de la fonction.
La fonction interne peut accéder aux variables définies dans sa propre portée, la portée de la fonction extérieure et la portée globale. Et la fonction externe peut accéder à la variable définie dans sa propre portée et la portée globale.
Exemple de fermeture :
Le résultat sera 20, somme de sa propre fonction interne, de sa fonction externe et de sa valeur de variable globale.
la source
Dans une situation normale, les variables sont liées par une règle de portée: les variables locales ne fonctionnent que dans la fonction définie. La fermeture est un moyen d'enfreindre temporairement cette règle pour plus de commodité.
dans le code ci-dessus,
lambda(|n| a_thing * n}
est la fermeture car ellea_thing
est référencée par le lambda (un créateur de fonction anonyme).Maintenant, si vous mettez la fonction anonyme résultante dans une variable de fonction.
foo enfreindra la règle de cadrage normale et commencera à utiliser 4 en interne.
renvoie 12.
la source
En bref, le pointeur de fonction n'est qu'un pointeur vers un emplacement dans la base de code de programme (comme le compteur de programme). Tandis que Closure = Function pointer + Stack frame .
.
la source
• Une fermeture est un sous-programme et l'environnement de référence où il a été défini
- L'environnement de référencement est nécessaire si le sous-programme peut être appelé à partir de n'importe quel endroit arbitraire du programme
- Un langage à portée statique qui n'autorise pas les sous-programmes imbriqués n'a pas besoin de fermetures
- Les fermetures ne sont nécessaires que si un sous-programme peut accéder aux variables dans les étendues d'imbrication et il peut être appelé de n'importe où
- Pour prendre en charge les fermetures, une implémentation peut devoir fournir une étendue illimitée à certaines variables (car un sous-programme peut accéder à une variable non locale qui n'est normalement plus active)
Exemple
la source
Voici un autre exemple réel, et en utilisant un langage de script populaire dans les jeux - Lua. J'ai dû changer légèrement la façon dont une fonction de bibliothèque fonctionnait pour éviter un problème avec stdin non disponible.
La valeur de old_dofile disparaît lorsque ce bloc de code termine sa portée (car il est local), mais la valeur a été incluse dans une fermeture, donc la nouvelle fonction de fichier redéfini PEUT y accéder, ou plutôt une copie stockée avec la fonction en tant que «upvalue».
la source
De Lua.org :
la source
Si vous êtes du monde Java, vous pouvez comparer une fermeture avec une fonction membre d'une classe. Regardez cet exemple
La fonction
g
est une fermeture: seg
fermea
. Elleg
peut donc être comparée à une fonction membre,a
peut être comparée à un champ de classe et la fonctionf
à une classe.la source
Fermetures Chaque fois que nous avons une fonction définie à l'intérieur d'une autre fonction, la fonction interne a accès aux variables déclarées dans la fonction externe. Les fermetures sont mieux expliquées avec des exemples. Dans l'extrait 2-18, vous pouvez voir que la fonction interne a accès à une variable (variableInOuterFunction) à partir de la portée externe. Les variables de la fonction externe ont été fermées par (ou liées dans) la fonction interne. D'où le terme de fermeture. Le concept en lui-même est assez simple et assez intuitif.
source: http://index-of.es/Varios/Basarat%20Ali%20Syed%20(auth.)-Beginning%20Node.js-Apress%20(2014).pdf
la source
Veuillez regarder ci-dessous le code pour comprendre la fermeture de manière plus approfondie:
Voici ce qui sera produit?
0,1,2,3,4
ce ne sera pas à5,5,5,5,5
cause de la fermetureAlors, comment ça va résoudre? La réponse est ci-dessous:
Permettez-moi d'expliquer simplement, quand une fonction créée rien ne se passe jusqu'à ce qu'elle appelle ainsi pour la boucle dans le 1er code appelé 5 fois mais pas appelé immédiatement alors quand elle est appelée, c'est-à-dire après 1 seconde et aussi c'est asynchrone donc avant que pour la boucle terminée et stocke la valeur 5 dans var i et enfin exécuter la
setTimeout
fonction cinq fois et imprimer5,5,5,5,5
Voici comment cela se résout en utilisant IIFE, c'est-à-dire l'expression de la fonction d'appel immédiat
Pour en savoir plus, veuillez comprendre le contexte d'exécution pour comprendre la clôture.
Il existe une autre solution pour résoudre ce problème en utilisant let (fonctionnalité ES6), mais sous le capot, la fonction ci-dessus fonctionne
=> Plus d'explications:
En mémoire, quand pour boucle exécuter l'image, faites comme ci-dessous:
Boucle 1)
Boucle 2)
Boucle 3)
Boucle 4)
Boucle 5)
Ici, i n'est pas exécuté, puis après la boucle complète, var i a stocké la valeur 5 en mémoire, mais sa portée est toujours visible dans sa fonction enfants, donc quand la fonction s'exécute à l'
setTimeout
envers cinq fois, elle s'imprime5,5,5,5,5
donc pour résoudre cette utilisation IIFE comme expliqué ci-dessus.
la source
Currying: Il vous permet d'évaluer partiellement une fonction en passant uniquement un sous-ensemble de ses arguments. Considère ceci:
Clôture: Une fermeture n'est rien d'autre que l'accès à une variable en dehors de la portée d'une fonction. Il est important de se rappeler qu'une fonction à l'intérieur d'une fonction ou une fonction imbriquée n'est pas une fermeture. Les fermetures sont toujours utilisées lorsque vous avez besoin d'accéder aux variables en dehors de la portée de la fonction.
la source
La fermeture est très simple. On peut le considérer comme suit: Fermeture = fonction + son environnement lexical
Considérez la fonction suivante:
Quelle sera la fermeture dans le cas ci-dessus? Fonction init () et variables dans son environnement lexical ie nom. Fermeture = init () + nom
Considérons une autre fonction:
Quelles seront les fermetures ici? La fonction interne peut accéder aux variables de la fonction externe. displayName () peut accéder au nom de variable déclaré dans la fonction parent, init (). Cependant, les mêmes variables locales dans displayName () seront utilisées si elles existent.
Fermeture 1: fonction init + (variable name + fonction displayName ()) -> portée lexicale
Fermeture 2: fonction displayName + (variable de nom) -> portée lexicale
la source
Les fermetures fournissent JavaScript à l'état.
État dans la programmation signifie simplement se souvenir des choses.
Exemple
Dans le cas ci-dessus, l'état est stocké dans la variable "a". Nous suivons en ajoutant 1 à "a" plusieurs fois. Nous ne pouvons le faire que parce que nous pouvons «nous souvenir» de la valeur. Le détenteur de l'état, "a", conserve cette valeur en mémoire.
Souvent, dans les langages de programmation, vous voulez garder une trace des choses, vous souvenir des informations et y accéder ultérieurement.
Ceci, dans d'autres langues , est généralement accompli grâce à l'utilisation de classes. Une classe, tout comme les variables, garde une trace de son état. Et les instances de cette classe, à leur tour, ont également un état en leur sein. État signifie simplement des informations que vous pouvez stocker et récupérer ultérieurement.
Exemple
Comment pouvons-nous accéder au "poids" depuis la méthode "render"? Eh bien, grâce à l'Etat. Chaque instance de la classe Bread peut rendre son propre poids en la lisant à partir de "l'état", un endroit en mémoire où nous pourrions stocker cette information.
Maintenant, JavaScript est un langage très unique qui n'a historiquement pas de classes (il en a maintenant, mais sous le capot, il n'y a que des fonctions et des variables), donc les fermetures permettent à JavaScript de se souvenir des choses et d'y accéder plus tard.
Exemple
L'exemple ci-dessus a atteint l'objectif de "maintien de l'état" avec une variable. C'est bien! Cependant, cela présente l'inconvénient que la variable (le détenteur de "l'état") est maintenant exposée. On peut faire mieux. Nous pouvons utiliser des fermetures.
Exemple
C'est fantastique.
Maintenant, notre fonction "count" peut compter. Il ne peut le faire que parce qu'il peut "tenir" l'état. L'état dans ce cas est la variable "n". Cette variable est maintenant fermée. Fermé dans le temps et l'espace. À temps parce que vous ne pourrez jamais le récupérer, le changer, lui attribuer une valeur ou interagir directement avec lui. Dans l'espace car il est géographiquement imbriqué dans la fonction "countGenerator".
Pourquoi est-ce fantastique? Parce que sans impliquer aucun autre outil sophistiqué et compliqué (par exemple des classes, des méthodes, des instances, etc.), nous sommes capables de 1. cacher 2. le contrôle à distance
On cache l'état, la variable "n", ce qui en fait une variable privée! Nous avons également créé une API qui peut contrôler cette variable d'une manière prédéfinie. En particulier, nous pouvons appeler l'API comme "count ()" et cela ajoute 1 à "n" à partir d'une "distance". En aucun cas, la forme ou la forme de quiconque ne pourra jamais accéder à "n" sauf via l'API.
JavaScript est vraiment incroyable dans sa simplicité.
Les fermetures expliquent en grande partie pourquoi.
la source
Un exemple simple dans Groovy pour votre référence:
la source