Compréhension approfondie des fermetures JavaScript
Une fermeture contient des variables libres (non liées à un objet spécifique) ; ces variables ne sont pas définies dans ce bloc de code ou dans un contexte global, mais sont définies dans l'environnement dans lequel le bloc de code est défini (variables locales). Le mot « fermeture » vient de la combinaison d'un bloc de code à exécuter (car les variables libres sont contenues à l'intérieur du bloc, ces variables libres et les objets auxquels elles font référence ne sont pas libérées) et de la liaison prévue pour les variables libres. Environnement informatique (portée). Dans cet article, nous vous donnerons une compréhension approfondie des fermetures JavaScript.
1. La portée des variables
Pour comprendre les fermetures, vous devez d'abord comprendre la portée des variables spéciales de Javascript.
La portée des variables n'est rien de plus que deux types : les variables globales et les variables locales.
La particularité du langage Javascript est que les variables globales peuvent être lues directement à l'intérieur de la fonction.
Code Js
var n=999;
Fonction f1(){
alert(n);
}
f1(); // 999
Par contre, la fonction ne peut pas être lue en dehors du fonction.
Code Js
fonction f1(){
var n=999;
}
alerte(n) ; // erreur
Il y a quelque chose à noter ici Lorsque vous déclarez des variables à l'intérieur d'une fonction, vous devez utiliser la commande var. Si vous ne l'utilisez pas, vous déclarez en fait une variable globale !
Code Js
fonction f1(){
n=999;
}
f1();
alerte(n); // 999
---------------- -------------------------------------------------- ----------------------------------------------------
2 . Comment lire les variables locales de l'extérieur ?
Pour diverses raisons, nous avons parfois besoin d'obtenir des variables locales au sein d'une fonction. Cependant, comme mentionné précédemment, cela n’est pas possible dans des circonstances normales et ne peut être réalisé que grâce à des solutions de contournement.
C'est-à-dire définir une fonction à l'intérieur de la fonction.
Code Js
fonction f1(){
n=999;
function f2(){
alert(n); Dans le code, la fonction f2 est incluse dans la fonction f1 À ce stade, toutes les variables locales à l'intérieur de f1 sont visibles par f2. Mais l’inverse ne fonctionne pas. Les variables locales à l’intérieur de f2 sont invisibles pour f1. Il s'agit de la structure unique de « portée de chaîne » du langage Javascript
L'objet enfant recherchera les variables de tous les objets parents niveau par niveau. Par conséquent, toutes les variables de l’objet parent sont visibles par l’objet enfant, mais l’inverse n’est pas vrai. Puisque f2 peut lire les variables locales dans f1, alors tant que f2 est utilisé comme valeur de retour, ne pouvons-nous pas lire ses variables internes en dehors de f1 ?
Code Js
fonction f1(){
n=999;
alert(n); }
return f2 >
var result=f1( );
résultat();
----- ----------------------------------- --------------- ----------------------------------- --------------- -
3. La notion de fermeture
La fonction f2 dans le code de la section précédente est une fermeture.La définition de « clôture » dans diverses littératures professionnelles est très abstraite et difficile à comprendre. Je crois comprendre qu'une fermeture est une fonction qui peut lire les variables internes d'autres fonctions. É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 ». Ainsi, par essence, la fermeture est un pont reliant l'intérieur d'une fonction à l'extérieur de la fonction.
------------------------------------------------------ ------ -------------------------------------------- ------ ----------b4. L'utilisation des fermetures
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 est de conserver les valeurs de ces variables en mémoire . Comment comprendre cette phrase ? Veuillez regarder le code ci-dessous.
Code Js
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n); }
}
var result=f1( 🎜> result(); / 999
nAdd(); // 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 cette 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.
------------------------------------------------------ ------ -------------------------------------------- ------ ----------
5. Points à noter lors de l'utilisation des fermetures
1) Parce que les fermetures créeront des fonctions. Les variables sont toutes stockées en mémoire, ce qui consomme beaucoup de mémoire, donc les fermetures ne peuvent pas être abusées, sinon cela entraînerait des problèmes de performances sur la page Web et pourrait provoquer des fuites de mémoire dans IE. La solution consiste à supprimer toutes les variables locales inutilisées avant de quitter la fonction.
2) La fermeture modifiera la valeur de la variable à l'intérieur de la fonction parent en dehors de la fonction parent. Par conséquent, si vous utilisez la fonction parent comme objet, la fermeture comme méthode publique et les variables internes comme valeur privée, vous devez faire attention à ne pas modifier la valeur de la variable à l'intérieur la fonction parent. ------------------------------------------------------ ------ -------------------------------------------- ------ ----------
6. Questions
Si vous pouvez comprendre les résultats de le code suivant, ça devrait aller Comprendre le mécanisme de fonctionnement des fermetures.
Code Jsvar name = "La fenêtre"; > return function(){ return this.name }; ;
alert(object.getNameFunc()()); // La fenêtre
---------- ----------------------- --------------------------- ----------------------- --------------------------
Exemple de fermeture JavaScript
fonction externalFun()
var a=0; function innerFun() { a++;
alert(a); } }innerFun()
erreur. La portée de innerFun() est à l'intérieur de externalFun(), et elle est appelée à l'extérieur de externalFun(). C'est faux. Remplacez
par ce qui suit, qui est une fermeture :
Code Js
function externalFun()
{
var a=0;
function innerFun()
{
a++;
alert(a);
}
return innerFun; //Notez ici
>
var obj=outerFun();
obj();//Le résultat est 1
obj(); //Le résultat est 2
var obj2=outerFun();obj2(
//Le résultat est 1
obj2() ; //Le résultat est 2
<.>--------------------------------------------------------------- ------ -------------------------------------------- ------
Regardons un autre exemple Code Js
fonction externalFun(){ var a =0;
alert(a);
>
var a=4;
outerFun();
alert(a);
résultat C'est
Parce que le mot-clé var est utilisé à l'intérieur de la fonction pour maintenir la portée d'un inside outFun(). encore une fois : Js Code
function externalFun(){
//No var
a =0;
alert(a); } var a=4;
outerFun();
alert(a);
Le résultat est
0,0
C'est vraiment étrange, pourquoi ?
La chaîne de portée est un terme qui décrit un chemin le long duquel la valeur d'une variable peut être déterminée. Lorsque a=0 est exécuté, parce que le mot-clé var n'est pas utilisé, l'opération d'affectation. suivra la chaîne de portée jusqu'à var a= 4; Et changera sa valeur.
Si vous ne comprenez pas très bien les fermetures JavaScript, veuillez lire l'article réimprimé ci-dessous : (Réimprimé : http://www.felixwoo.com/archives/247)
L'explication officielle est la suivante : une fermeture est une expression (généralement une fonction) qui a de nombreuses variables et un environnement lié à ces variables, donc ces variables en font également partie Je crois que peu de gens peuvent comprendre cette phrase directement, car sa description est trop académique. En fait, cette phrase est : Toutes les fonctions en JavaScript sont un package
. la fermeture générée par la fonction imbriquée est plus puissante, ce que l'on appelle la plupart du temps « fermeture » :
Ce code a deux caractéristiques :
1 2 3 4 |
|
2. La fonction a renvoie la fonction b
La relation de référence est la suivante :
De cette façon. , après avoir exécuté var c=a(), la variable c pointe en fait vers la fonction b. Après avoir exécuté c(), une fenêtre apparaîtra pour afficher la valeur i (la première fois est 1). Ce code crée en fait une fermeture. Pourquoi ? Parce que la variable c en dehors de la fonction a fait référence à la fonction b à l'intérieur de la fonction a, c'est-à-dire :
Quand la fonction interne b de la fonction a est référencée par une variable en dehors de la fonction a, une fermeture est créée
Rendons les choses plus approfondies. Certains, ce qu'on appelle la "fermeture", consiste à définir une autre fonction comme fonction de méthode de l'objet cible dans. le corps du constructeur, et la fonction méthode de cet objet fait à son tour référence à la variable temporaire dans le corps de la fonction externe. Cela fait que tant que l'objet cible est vivant, sa méthode peut toujours être conservée dans l'objet, et la variable temporaire. La valeur utilisée par le corps du constructeur d'origine peut être indirectement conservée. Bien que l'appel initial du constructeur soit terminé et que les noms des variables temporaires aient disparu, elles sont toujours dans la méthode de l'objet cible. La valeur de la variable peut toujours être référencée. et la valeur n'est accessible que via cette méthode. Même si le même constructeur est appelé à nouveau, seuls les nouveaux objets et méthodes seront générés, et les nouvelles variables temporaires ne correspondront qu'aux nouvelles valeurs. >2. Quelle est la fonction de la fermeture ?
En bref, la fonction de la fermeture est Après l'exécution et le retour de a, la fermeture empêche le mécanisme de récupération de place de Javascript. GC de récupérer les ressources occupées par a, car l'exécution de la fonction interne de a b dépend des variables de a. Il s'agit d'une explication très simple du rôle de la fermeture. La description n'est ni professionnelle ni rigoureuse, mais le sens général est le suivant. . Comprendre la fermeture nécessite un processus étape par étape .
在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c(),i都是自加1后alert出i的值。
那 么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引 用,因此函数a和b互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。(关于Javascript的垃圾回收机制将在后面详细介绍)
三、闭包内的微观世界
如果要更加深入的了解闭包以及函数a和嵌套函数b的关系,我们需要引入另外几个概念:函数的执行环境(excution context)、活动对象(call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。
当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。
当执行函数a的时候,a会进入相应的执行环境(excution context)。
在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即a.scope=a的作用域链。
然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码直接访问。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和window对象。
下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。
最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。
到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。
当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象,如下图所示:
如图所示,当在函数b中访问一个变量的时候,搜索顺序是:
先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依次查找,直到找到为止。
如果函数b存在prototype原型对象,则在查找完自身的活动对象后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。
如果整个作用域链上都无法找到,则返回undefined。
小结,本段中提到了两个重要的词语:函数的定义与执行。文中提到函数的作用域是在定义函数时候就已经确定,而不是在执行的时候确定(参看步骤1和3)。用一段代码来说明这个问题:
1 2 |
|
这段代码中变量h指向了f中的那个匿名函数(由g返回)。
假设函数h的作用域是在执行alert(h())确定的,那么此时h的作用域链是:h的活动对象->alert的活动对象->window对象。
假设函数h的作用域是在定义时确定的,就是说h指向的那个匿名函数在定义的时候就已经确定了作用域。那么在执行的时候,h的作用域链为:h的活动对象->f的活动对象->window对象。
如果第一种假设成立,那输出值就是undefined;如果第二种假设成立,输出值则为1。
运行结果证明了第2个假设是正确的,说明函数的作用域确实是在定义这个函数的时候就已经确定了。
四、闭包的应用场景
保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
Maintient une variable en mémoire. Toujours comme dans l'exemple précédent, en raison de la fermeture, i dans la fonction a existe toujours en mémoire, donc à chaque fois que c() est exécuté, i sera incrémenté de 1.
-
Implémentez les propriétés et méthodes privées JS en protégeant la sécurité des variables (non accessibles en externe)
Les propriétés et méthodes privées ne sont pas accessibles en dehors du constructeurfonction Constructeur(...){
var que = ce;
var nom de membre = valeur;
fonctionnom du membre(...){...}
}
Les trois points ci-dessus sont les scénarios d'application les plus élémentaires des fermetures. De nombreux cas classiques en découlent.
5. Le mécanisme de récupération de place de Javascript
En Javascript, si un l'objet n'est plus référencé, l'objet sera recyclé par GC. Si deux objets font référence l'un à l'autre et ne sont plus référencés par un tiers, alors les deux objets qui font référence l'un à l'autre seront également recyclés. Parce que la fonction a est référencée par b, et b est référencé par c en dehors de a, c'est pourquoi la fonction a ne sera pas recyclée après exécution.
Comprendre les fermetures JavaScript est le seul moyen de devenir un programmeur JS avancé. Ce n'est qu'en comprenant son interprétation et son mécanisme de fonctionnement que vous pourrez écrire un code plus sûr et plus élégant. Le contenu ci-dessus est une explication détaillée des fermetures JavaScript. J'espère qu'il pourra aider tout le monde.
Recommandations associées :
Explication détaillée des formes courantes de fermetures JS
Explication détaillée des fermetures JS classiques
Explication détaillée des connaissances js Closure_basic
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

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

AI Hentai Generator
Générez AI Hentai gratuitement.

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)

La technologie de détection et de reconnaissance des visages est déjà une technologie relativement mature et largement utilisée. Actuellement, le langage d'application Internet le plus utilisé est JS. La mise en œuvre de la détection et de la reconnaissance faciale sur le front-end Web présente des avantages et des inconvénients par rapport à la reconnaissance faciale back-end. Les avantages incluent la réduction de l'interaction réseau et de la reconnaissance en temps réel, ce qui réduit considérablement le temps d'attente des utilisateurs et améliore l'expérience utilisateur. Les inconvénients sont les suivants : il est limité par la taille du modèle et la précision est également limitée ; Comment utiliser js pour implémenter la détection de visage sur le web ? Afin de mettre en œuvre la reconnaissance faciale sur le Web, vous devez être familier avec les langages et technologies de programmation associés, tels que JavaScript, HTML, CSS, WebRTC, etc. Dans le même temps, vous devez également maîtriser les technologies pertinentes de vision par ordinateur et d’intelligence artificielle. Il convient de noter qu'en raison de la conception du côté Web

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.

La relation entre js et vue : 1. JS comme pierre angulaire du développement Web ; 2. L'essor de Vue.js en tant que framework front-end ; 3. La relation complémentaire entre JS et Vue ; Vue.

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.

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.

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.
