Maison interface Web js tutoriel Comprendre et utiliser le mécanisme de fermeture de JavaScript_Connaissances de base

Comprendre et utiliser le mécanisme de fermeture de JavaScript_Connaissances de base

May 16, 2016 pm 03:45 PM
javascript 闭包

Le grand camarade Einstein a dit un jour : "Si vous ne pouvez pas expliquer clairement quelque chose à un enfant de 6 ans, alors vous ne le comprenez pas vous-même." Cependant, lorsque j’ai expliqué ce qu’étaient les fermetures à un ami de 27 ans, j’ai complètement échoué.

Il s'agissait à l'origine d'une question soulevée par un ami étranger sur Stack Overflow à propos des fermetures JavaScript. Cependant, puisque cette question a été posée sur Stack Overflow, bien sûr de nombreux experts viendront y répondre. Certaines réponses sont effectivement des classiques, comme la suivante :

.

Si vous définissez une fonction interne dans une fonction externe, c'est-à-dire une fonction imbriquée, alors la fonction interne peut également accéder aux variables de la fonction externe :

function foo(x) {
 var tmp = 3;
 function bar(y) {
 alert(x + y + (++tmp));
 }
 bar(10);
}

foo(2); // alert 16
foo(2); // alert 16
foo(2); // alert 16

Copier après la connexion

Ce code peut être exécuté correctement et renvoie le résultat : 16, car bar peut accéder à la variable tmp de la fonction externe et peut également accéder au paramètre x de la fonction externe foo. Mais l’exemple ci-dessus n’est pas une clôture !

Pour implémenter la fermeture, la fonction interne doit être renvoyée comme valeur de retour de la fonction externe. Avant de revenir, la fonction interne verrouillera toutes les variables de la fonction externe qui ont été accédées dans la mémoire. ces variables Il résidera dans la mémoire du bar et ne sera pas recyclé par le garbage collector, comme suit :

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + (++tmp));
 }
}
var bar = foo(2); // bar 现在是个闭包了
bar(10); // alert 16
bar(10); // alert 17
bar(10); // alert 18

Copier après la connexion

Dans le code ci-dessus, lorsque bar est exécuté pour la première fois, le résultat sera toujours renvoyé : 16, car bar peut toujours accéder à x et tmp, bien qu'il n'existe plus directement dans la portée de foo. Ainsi, puisque tmp est verrouillé lors de la fermeture de bar, tmp sera incrémenté à chaque fois que bar est exécuté, donc lorsque bar est exécuté pour la deuxième et la troisième fois, 17 et 18 sont renvoyés respectivement.

Dans cet exemple, x est juste une valeur pure Lorsque foo est appelé, la valeur x sera copiée dans foo en tant que paramètre.

Mais lorsque JavaScript gère des objets, il utilise toujours des références. Si vous appelez foo avec un objet comme paramètre, alors ce qui est passé dans foo est en fait une référence à l'objet d'origine, donc l'objet d'origine équivaut également à être fermé. . , comme suit :

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + tmp++);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar = foo(age); // bar 现在是个闭包了
bar(10); // alert 15 1
bar(10); // alert 16 2
bar(10); // alert 17 3

Copier après la connexion

Comme prévu, chaque fois que bar(10) est exécuté, non seulement tmp est incrémenté, mais x.memb est également incrémenté, car x dans le corps de la fonction et age en dehors de la fonction font référence au même objet.

via http://stackoverflow.com/questions/111102/how-do-javascript-closures-work

Supplément : Grâce aux exemples ci-dessus, vous devriez être en mesure de comprendre plus clairement les fermetures. Si vous pensez l'avoir compris, vous pouvez tenter de deviner le résultat de l'exécution du code suivant :

function foo(x) {
 var tmp = 3;
 return function (y) {
 alert(x + y + tmp++);
 x.memb = x.memb ? x.memb + 1 : 1;
 alert(x.memb);
 }
}
var age = new Number(2);
var bar1 = foo(age); // bar1 现在是个闭包了
bar1(10); // alert 15 1
bar1(10); // alert 16 2
bar1(10); // alert 17 3

var bar2 = foo(age); // bar2 现在也是个闭包了
bar2(10); // alert ? ?
bar2(10); // alert ? ?
bar2(10); // alert ? ?

bar1(10); // alert ? ?
bar1(10); // alert ? ?
bar1(10); // alert ? ?

Copier après la connexion

Lorsqu'elles sont utilisées dans la pratique, les fermetures peuvent créer des designs très élégants, permettant de personnaliser les différentes méthodes de calcul définies sur funarg. Voici un exemple de tri par tableau, qui accepte une fonction de condition de tri comme paramètre :

[1, 2, 3].sort(function (a, b) {
 ... // 排序条件
});
Copier après la connexion

Le même exemple est que la méthode map d'un tableau mappe le tableau d'origine à un nouveau tableau en fonction des conditions définies dans la fonction :

[1, 2, 3].map(function (element) {
 return element * 2;
}); // [2, 4, 6]
Copier après la connexion

À l'aide de paramètres fonctionnels, vous pouvez facilement implémenter une méthode de recherche et prendre en charge des conditions de recherche illimitées :

someCollection.find(function (element) {
 return element.someProperty == 'searchCondition';
});
Copier après la connexion

Il existe également des fonctions d'application, telles que la méthode commune forEach, qui applique la fonction à chaque élément du tableau :

[1, 2, 3].forEach(function (element) {
 if (element % 2 != 0) {
  alert(element);
 }
}); // 1, 3
Copier après la connexion

À propos, les méthodes apply et call des objets fonction peuvent également être utilisées comme fonctions d'application dans la programmation fonctionnelle. Ici, nous les considérons comme des fonctions d'application - des fonctions appliquées aux paramètres (dans apply c'est la liste des paramètres, dans call c'est un paramètre indépendant) :

(function () {
 alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);
Copier après la connexion

Les fermetures ont une autre application très importante : les appels différés :

var a = 10;
setTimeout(function () {
 alert(a); // 10, after one second
}, 1000);
还有回调函数:

//...
var x = 10;
// only for example
xmlHttpRequestObject.onreadystatechange = function () {
 // 当数据就绪的时候,才会调用;
 // 这里,不论是在哪个上下文中创建
 // 此时变量“x”的值已经存在了
 alert(x); // 10
};
//...

Copier après la connexion

Vous pouvez également créer des étendues d'encapsulation pour masquer les objets d'assistance :

var foo = {};

// 初始化
(function (object) {

 var x = 10;

 object.getX = function _getX() {
  return x;
 };

})(foo);

alert(foo.getX()); // 获得闭包 "x" – 10

Copier après la connexion

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

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 !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

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

Quelle est la signification de la fermeture dans l'expression lambda C++ ? Quelle est la signification de la fermeture dans l'expression lambda C++ ? Apr 17, 2024 pm 06:15 PM

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.

Comment implémenter la fermeture dans une expression C++ Lambda ? Comment implémenter la fermeture dans une expression C++ Lambda ? Jun 01, 2024 pm 05:50 PM

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.

Quels sont les avantages et les inconvénients des fermetures dans les fonctions C++ ? Quels sont les avantages et les inconvénients des fermetures dans les fonctions C++ ? Apr 25, 2024 pm 01:33 PM

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.

Résoudre le problème de fuite de mémoire causé par les fermetures Résoudre le problème de fuite de mémoire causé par les fermetures Feb 18, 2024 pm 03:20 PM

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é,

Le rôle de la fermeture de la fonction Golang dans les tests Le rôle de la fermeture de la fonction Golang dans les tests Apr 24, 2024 am 08:54 AM

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.

Appels enchaînés et fermetures de fonctions PHP Appels enchaînés et fermetures de fonctions PHP Apr 13, 2024 am 11:18 AM

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 Golang L'impact des pointeurs de fonction et des fermetures sur les performances de Golang Apr 15, 2024 am 10:36 AM

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.

Comment les fermetures sont-elles implémentées en Java ? Comment les fermetures sont-elles implémentées en Java ? May 03, 2024 pm 12:48 PM

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.

See all articles