


Explication détaillée des fermetures JavaScript_Connaissances de base
Dans le dernier article, nous avons donné un aperçu de la pré-interprétation. Avant d'écrire cet article de blog, nous avions prévu d'écrire quelques cas classiques. Considérant que ces cas sont relativement complets, nous avons rédigé cet article étape par étape, donc. que nous pouvons Il est également plus facile de commencer à apprendre et à approfondir JavaScript.
Préface
Un collègue est allé passer un entretien et l'intervieweur a posé une question : pouvez-vous rédiger une conclusion et me laisser y jeter un œil ? Mon collègue a donc rapidement écrit le code suivant :
fonction fn(){
alert('Bonjour JavaScript Closure !!!'); // Bon sang, le texte E n'est pas bon, j'ai donc dû trouver un traducteur pour écrire les mots de fermeture
>
fn();
Puis l'intervieweur a secoué la tête et a dit : « Comment cela peut-il être appelé une clôture ? » En fin de compte, les deux n'ont pas pu se disputer, et le collègue est parti de manière décisive. Que diable fait l'intervieweur ? (Cette histoire est purement fictive, toute similitude est purement fortuite)
La fermeture est peut-être une technologie « haut de gamme et difficile à apprendre » aux yeux de beaucoup de gens. Peut-être qu'aux yeux de beaucoup de gens, c'est la seule qui compte comme fermeture :
Exemple 1 :
fonction fn() {
Fonction de retour () {
alert('Exemple 1');
>
>
fn()();
Exemple 1 PS : Cela n’a pas l’air très avancé, on dirait que cette personne n’est pas très bonne !
Exemple 2 :
;(fonction () {
alert('Exemple 2');
})();
Exemple 2 PS : Celui-ci a l'air plus avancé que le précédent, et un point-virgule est ajouté avant la première parenthèse. Eh bien, laissons cette question ici pour l'instant et nous en reparlerons plus tard.
Exemple 3 :
~fonction fn() {
alert('Exemple 3')
}();
Exemple 3 PS : C’est le plus avancé, c’est incroyable je ne lis pas beaucoup, alors ne me mentez pas !
Je ne lis pas beaucoup, donc je ne peux écrire que ces trois types de « clôtures ». Je pense que les autres blogueurs peuvent écrire des « clôtures » plus nombreuses et de meilleure qualité ; Je connais déjà le mécanisme de fonctionnement de la fonction. Ce doit être la portée. Je ne veux vraiment pas ajouter cette portée au titre. Cela semble toujours presque dénué de sens. Vieille habitude, codez d'abord :
var n = 10;
fonction fn(){
alerte(n);
var n = 9;
alerte(n);
>
fn();
Pour faire simple, faisons un dessin (l'auteur n'utilisera que le logiciel de dessin fourni avec Windows. S'il en existe un meilleur, merci de le recommander) pour l'analyser :
Analyse 1
Sur l'image, nous voyons deux portées, l'une est la portée de la fenêtre (portée de niveau supérieur) et l'autre est une portée privée formée lorsque fn est appelé ; alors qu'est-ce qu'une portée, la portée est en fait un environnement d'exécution de code. Par exemple, l'environnement d'apprentissage d'un élève est l'école, ce qui équivaut à sa portée. Si cet élève est très méchant et va souvent dans un cybercafé pour jouer à des jeux le soir, cela équivaut à former un environnement privé, et cette portée est la. Cybercafé. D'accord! Ce marron ressemble tellement au masturbateur lui-même que je n'ai pas pu m'empêcher de soupirer : "Si tu ne travailles pas dur quand tu es jeune, tu te feras botter quand tu seras grand." Revenons au sujet, en fait, la définition de la fonction fn est une description pointant vers un morceau de code (case rouge dans l'image). Lorsque fn est appelé (case verte dans l'image), une portée sera bien sûr formée. , dans cette portée Le code sera également pré-interprété avant l'exécution. Je ne vous dirai pas que cette portée sera détruite après son exécution. Appeler à nouveau ce fn formera également une nouvelle portée, puis une pré-interprétation avant l'exécution, puis le code est exécuté détruit après l'exécution finale.
Comprendre les fermetures
Nous savons que lorsqu'une fonction est appelée, elle formera une portée privée (environnement d'exécution), et cette portée privée est une fermeture. Avec le recul, la fermeture est-elle toujours le légendaire « grand et difficile à maîtriser » ? Revenons au premier récit d'interview et aux trois exemples que j'ai écrits. Ce sont en fait des fermetures. Pour être précis, ces trois exemples sont tous des formes courantes de fermetures.
Scénarios d'application
Maintenant, il existe une telle exigence : il y a une balise ul dans la page HTML, et il y a 5 balises li sous la ul. Il est nécessaire de cliquer sur n'importe quel li, et la position d'index (l'index commence à partir de 0). le li cliqué apparaîtra et la structure HTML comme suit :
- Liste 1
- Liste 2
- Liste 3
- Liste 4
- Liste 5
Étant malin, j'ai rapidement écrit le code suivant :
var lis = document.getElementById('ul').getElementsByTagName('li');
pour (var i = 0, len = lis.length; i < len; i ) {
lis[i].onclick = fonction () {
alerte(i);
};
>
Test final pour voir si cette exigence est parfaitement réalisée :
J'ai découvert que peu importe le nombre de fois que je clique, ce résultat finira par apparaître, et le résultat attendu est : cliquez sur la liste 1 pour afficher 0, cliquez sur la liste 2 pour afficher 1, cliquez sur la liste 3 pour pop up 2... Je veux juste utiliser cette photo en ce moment Pour décrire mon humeur actuelle :
(À quoi cela ressemble lorsque le prototype ne fonctionne pas comme prévu lors de la démonstration)
Comment cela peut-il être fait ? Pourquoi 5 apparaît-il toujours ? C'est théoriquement correct ! Faisons un dessin pour l'analyser :
En fait, le onclick que nous venons de donner à chaque li est en fait une chaîne de description enregistrée d'une fonction. Le contenu de cette chaîne est le contenu de la case rouge dans l'image ci-dessus. J'ai une photo avec la vérité :
Entrez : lis[4].onclick dans la console Chrome, la valeur est la description de la fonction. Lorsque nous cliquons sur la cinquième liste, cela équivaut en fait à lis[4].onclick(), appelant cette description de fonction. Nous savons que la fonction formera une portée privée lorsqu'elle sera appelée et exécutée dans cette portée privée. est également pré-interprété en premier, puis le code est exécuté à ce moment-là, i est trouvé Il n'y a pas de i dans la portée privée actuelle, puis i est trouvé dans la portée de la fenêtre, donc 5 apparaît à chaque fois que vous cliquez. .
De toute évidence, le code ci-dessus ne peut pas répondre à cette exigence. Il est incorrect pour nous d'écrire le code comme celui-ci. Réfléchissons à la cause du problème ? En fait, la raison est qu'à chaque fois que vous cliquez, vous lisez le i sous la fenêtre. A ce moment, la valeur de i est déjà 5, vous avez donc le code suivant :
.Méthode 1 :
var lis = document.getElementById('ul').getElementsByTagName('li');
fonction fn(i) {
Fonction de retour () {
alerte(i);
>
>
pour (var i = 0, len = lis.length; i < len; i ) {
lis[i].onclick = fn(i);
>
Méthode 2 :
var lis = document.getElementById('ul').getElementsByTagName('li');
pour (var i = 0, len = lis.length; i < len; i ) {
;(fonction (i) {
lis[i].onclick = function () {
alerte(i);
};
})(i);
>
Méthode 3 :
var lis = document.getElementById('ul').getElementsByTagName('li');
pour (var i = 0, len = lis.length; i < len; i ) {
lis[i].onclick = fonction fn(i) {
fonction de retour () {
alerte(i);
>
}(je);
>
J'ai écrit trois méthodes d'un seul coup. L'idée est la même, c'est à dire de stocker la variable i dans une variable privée. Ici, je ne parlerai que de la deuxième méthode. Bien sûr, si vous en comprenez une, vous. comprendra le reste. Comme d'habitude, on dessine des images à analyser étape par étape :
J'ai décrit l'intégralité de l'exécution du code en détail. Il convient de noter que l'attribut onclick de chaque li doit occuper la portée (function(i){…})(i) Lorsque cette fonction est exécutée, elle ne le sera pas. être détruit car il est occupé par un li externe (ce li est sous la portée de la fenêtre), donc cette portée ne sera pas détruite. Lorsqu'un li est cliqué, function(){ alert(i); } sera exécuté et une portée sera formée. Cette portée n'a pas de i, et elle ira à (function(){ ... })(. i) scope. Trouvez i, et enfin trouvez i dans le paramètre formel. La valeur de ce paramètre formel i est transmise lors de la boucle for ; cet exemple utilise intelligemment des fermetures pour stocker les valeurs, ce qui résout parfaitement le problème.
PS : je viens de mentionner pourquoi un point-virgule est ajouté devant (function(i){ … })(i). La raison est d'éviter que l'instruction précédente oublie d'ajouter un point-virgule, ce qui provoquerait des erreurs JavaScript lors du processus. analyse. C'est tout. Bien sûr, l'un des scénarios d'application ci-dessus est le principe d'implémentation des onglets. Il peut y avoir d'autres méthodes d'implémentation, telles que les méthodes d'attributs personnalisées et la recherche d'index via les relations entre les nœuds DOM. L'objectif principal de l'utilisation de cette méthode est d'approfondir la compréhension des fermetures. .
Résumé
Les fermetures ne sont pas légendaires et difficiles à maîtriser. L'essentiel est de comprendre la définition et l'appel d'une fonction. Lorsqu'une fonction est appelée, une nouvelle portée privée est formée. cette portée ne sera pas détruite. Lu Zhu a très peu lu, j'aimerais donc demander à mes collègues blogueurs de me corriger si je me trompe. Je voudrais également remercier tout le monde pour leur soutien aux articles de Lu Zhu.

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

En C++, une fermeture est une expression lambda qui peut accéder à des variables externes. Pour créer une fermeture, capturez la variable externe dans l'expression lambda. Les fermetures offrent des avantages tels que la réutilisabilité, la dissimulation des informations et une évaluation paresseuse. Ils sont utiles dans des situations réelles telles que les gestionnaires d'événements, où la fermeture peut toujours accéder aux variables externes même si elles sont détruites.

Les expressions C++ Lambda prennent en charge les fermetures, qui enregistrent les variables de portée de fonction et les rendent accessibles aux fonctions. La syntaxe est [capture-list](parameters)->return-type{function-body}. capture-list définit les variables à capturer. Vous pouvez utiliser [=] pour capturer toutes les variables locales par valeur, [&] pour capturer toutes les variables locales par référence, ou [variable1, variable2,...] pour capturer des variables spécifiques. Les expressions Lambda ne peuvent accéder qu'aux variables capturées mais ne peuvent pas modifier la valeur d'origine.

Une fermeture est une fonction imbriquée qui peut accéder aux variables dans la portée de la fonction externe. Ses avantages incluent l'encapsulation des données, la conservation de l'état et la flexibilité. Les inconvénients incluent la consommation de mémoire, l’impact sur les performances et la complexité du débogage. De plus, les fermetures peuvent créer des fonctions anonymes et les transmettre à d'autres fonctions sous forme de rappels ou d'arguments.

Titre : Fuites de mémoire causées par les fermetures et solutions Introduction : Les fermetures sont un concept très courant en JavaScript, qui permettent aux fonctions internes d'accéder aux variables des fonctions externes. Cependant, les fermetures peuvent provoquer des fuites de mémoire si elles ne sont pas utilisées correctement. Cet article explorera le problème de fuite de mémoire provoqué par les fermetures et fournira des solutions et des exemples de code spécifiques. 1. Fuites de mémoire causées par les fermetures La caractéristique des fermetures est que les fonctions internes peuvent accéder aux variables des fonctions externes, ce qui signifie que les variables référencées dans les fermetures ne seront pas récupérées. S'il est mal utilisé,

Les fermetures de fonctions du langage Go jouent un rôle essentiel dans les tests unitaires : Capture de valeurs : les fermetures peuvent accéder aux variables dans la portée externe, permettant ainsi de capturer et de réutiliser les paramètres de test dans des fonctions imbriquées. Simplifiez le code de test : en capturant les valeurs, les fermetures simplifient le code de test en éliminant le besoin de définir des paramètres à plusieurs reprises pour chaque boucle. Améliorez la lisibilité : utilisez des fermetures pour organiser la logique de test, rendant ainsi le code de test plus clair et plus facile à lire.

Oui, la simplicité et la lisibilité du code peuvent être optimisées grâce à des appels et des fermetures enchaînés : les appels en chaîne lient les appels de fonction dans une interface fluide. Les fermetures créent des blocs de code réutilisables et accèdent à des variables en dehors des fonctions.

L'impact des pointeurs de fonction et des fermetures sur les performances de Go est le suivant : Pointeurs de fonction : légèrement plus lents que les appels directs, mais améliorent la lisibilité et la réutilisabilité. Fermetures : généralement plus lentes, mais encapsulent les données et le comportement. Cas pratique : les pointeurs de fonction peuvent optimiser les algorithmes de tri et les fermetures peuvent créer des gestionnaires d'événements, mais ils entraîneront des pertes de performances.

Les fermetures en Java permettent aux fonctions internes d'accéder aux variables de portée externe même si la fonction externe est terminée. Implémentée via des classes internes anonymes, la classe interne contient une référence à la classe externe et maintient les variables externes actives. Les fermetures augmentent la flexibilité du code, mais vous devez être conscient du risque de fuite de mémoire, car les références à des variables externes par des classes internes anonymes maintiennent ces variables en vie.
