La fermeture (fermeture) est un seuil très important pour maîtriser Javascript du débutant à l'approfondissement. C'est une difficulté du langage Javascript et aussi sa caractéristique de nombreuses applications avancées. tout dépend de la fermeture. Notez mes notes d'étude ci-dessous~
Explication détaillée de la fermeture de JavaScript (Closure)
Explication approfondie de JavaScript This
Une introduction approfondie à la chaîne de prototypes et à l'héritage de JavaScript
Dans la programmation front-end, l'utilisation de fermetures est très courante Nous utilisons souvent des fermetures intentionnellement ou non, directement ou indirectement. Les fermetures peuvent rendre le transfert de données plus flexible (comme la gestion de certains événements de clic)
!function() { var localData = "localData here"; document.addEventListener('click', //处理点击事件时用到了外部局部变量,比如这里的localData function(){ console.log(localData); }); }();
Un autre exemple est l'exemple suivant : (N'est-ce pas très convivial ~~)
!function() { var localData = "localData here"; var url = "http://www.baidu.com/"; $.ajax({ url : url, success : function() { // do sth... console.log(localData); } }); }();
Regardons un autre exemple~~Cette situation est ce que nous appelons habituellement la fermeture
function outer() { var localVal = 30; return function(){ return localVal; } } var func = outer(); func(); // 30
Dans cet exemple, external() est appelé pour renvoyer la fonction anonyme function() Dans cette fonction anonyme, la fonction locale. La variable localVal de external() est accessible. Une fois l'appel external() terminé, lorsque func() est à nouveau appelée, la variable locale localVal de external() est toujours accessible
la fermeture est différente de la fonction générale Une fonction qui permet à une fonction d'accéder toujours à des variables non locales lorsqu'elle est appelée en dehors de la portée lexicale immédiate. – Wikipédia
Une fermeture est une fonction qui peut lire les variables internes d'autres fonctions. – Ruan Yifeng
Étant donné que dans le langage Javascript, seules les sous-fonctions à l'intérieur de la fonction peuvent lire les variables locales, les fermetures peuvent être simplement comprises comme des « fonctions définies à l'intérieur d'une fonction ».
Donc, par essence, la fermeture est un pont reliant l'intérieur d'une fonction à l'extérieur de la fonction
Cette partie est reproduite à partir de ce blog post
Les fermetures peuvent être utilisées dans de nombreux endroits. Il a deux utilisations principales : l’une consiste à lire les variables à l’intérieur de la fonction, comme mentionné précédemment, et l’autre consiste à conserver les valeurs de ces variables en mémoire.
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
Dans ce code, le résultat est en fait la fonction de fermeture f2. Il a été exécuté deux fois, la première fois, la valeur était de 999, la deuxième fois, la valeur était de 1 000. Cela prouve que la variable locale n dans la fonction f1 est toujours stockée en mémoire et n'est pas automatiquement effacée après l'appel de f1.
Pourquoi cela se produit-il ? La raison en est que f1 est la fonction parent de f2 et que f2 est affecté à une variable globale, ce qui fait que f2 est toujours en mémoire, et l'existence de f2 dépend de f1, donc f1 est toujours en mémoire et ne sera pas supprimé. une fois l'appel terminé, recyclé par le mécanisme de récupération de place (garbage collection).
Une autre chose à noter dans ce code est la ligne "nAdd=function(){n =1}". Tout d'abord, le mot-clé var n'est pas utilisé avant nAdd, donc nAdd est plutôt une variable globale. que les variables locales. Deuxièmement, la valeur de nAdd est une fonction anonyme, et la fonction anonyme elle-même est également une fermeture, donc nAdd est équivalent à un setter, qui peut opérer sur des variables locales à l'intérieur de la fonction en dehors de la fonction.
(function() { var _userId = 23492; var _typeId = 'item'; var export = {}; function converter(userId) { return +userId; } export.getUserId = function() { return converter(_userId); } export.getTypeId = function() { return _typeId; } window.export = export; //通过此方式输出 }()); export.getUserId(); // 23492 export.getTypeId(); // item export._userId; // undefined export._typeId; // undefined export.converter; // undefined
Utiliser les caractéristiques des fermetures permet d'encapsuler certaines fonctions complexes Logiquement, dans cet exemple, les méthodes d'exportation (getUserId, getTypeId) sont appelées pour accéder indirectement aux variables privées de la fonction, mais _userId ne peut pas être obtenu en appelant directement export._userId. Il s'agit également d'une fonctionnalité couramment utilisée dans Node~
Dans le cas suivant, nous ajoutons 3 p, les valeurs sont aaa, bbb, ccc Ce que nous voulons réaliser, c'est cliquer sur aaa pour sortir 1, cliquer sur bbb pour sortir 2, cliquer sur ccc pour sortir 3
document.body.innerHTML = "<p id=p1>aaa</p>" + "<p id=p2>bbb</p><p id=p3>ccc</p>"; for (var i = 1; i < 4; i++) { document.getElementById('p' + i). addEventListener('click', function() { alert(i); // all are 4! }); }
<. 🎜>
Par conséquent, cliquer sur aaa, bbb ou ccc sont tous alert(4)~~Le problème est que la valeur dei est déjà 4 lorsque l'initialisation est terminé
Pour obtenir ce que nous voulons, cliquez sur aaa pour sortir 1, cliquez sur bbb pour sortir 2 et cliquez sur ccc pour sortir 3. Nous devons utiliser la technique de fermeture dans chaque boucle, enveloppez-la avec. une fonction anonyme qui est exécutée immédiatement. Si vous faites cela, la valeur de alert(i) sera à chaque fois extraite de i dans l'environnement de fermeture. Ce i produira 1, 2 et 3 de l'affectation i de chaque boucle <. 🎜>document.body.innerHTML = "<p id=p1>aaa</p>" + "<p id=p2>bbb</p>" + "<p id=p3>ccc</p>"; for (var i = 1; i < 4; i++) { !function(i){ //②再用这个参数i,到getElementById()中引用 document.getElementById('p' + i). addEventListener('click', function() { alert(i); // 1,2,3 }); }(i); //①把遍历的1,2,3的值传到匿名函数里面 }
Questions de réflexion
Fragment de code 1
Fragment de code 2var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());