Maison  >  Article  >  développement back-end  >  Comment comprendre les fermetures et les classes en js

Comment comprendre les fermetures et les classes en js

一个新手
一个新手original
2017-10-23 09:22:291652parcourir

Fermeture

Regardons d'abord la définition de Wikipédia

En informatique, la fermeture (anglais : Closure), également connue sous le nom de fermeture lexicale (Lexical Closure) ou fonction Closures sont des fonctions qui font référence à des variables libres. La variable libre référencée restera avec la fonction même après avoir quitté l'environnement dans lequel elle a été créée. Il existe donc une autre façon de dire qu’une fermeture est une entité composée d’une fonction et de son environnement de référence associé. Les fermetures peuvent avoir plusieurs instances au moment de l'exécution, et différents environnements de référence et la même combinaison de fonctions peuvent produire différentes instances.

Pour comprendre cette phrase simplement, il y a deux points clés :
1. Variable libre 2. Fonction (faisant référence à une variable libre).

Parlons d'abord des variables libres :

Quand on définit une variable, si on ne lui précise pas de contraintes, c'est une variable libre. Par exemple :

x ∈  (0,99)
f(x,y)

Dans la fonction f(x,y), x est la variable contrainte et y est la variable libre.

Plus précisément en JavaScript, regardons un exemple :


var x = 0;
function foo (y) {
    var z = 2;
    return x + y + z;}foo (3); // 3

Si elle est convertie en pensée mathématique, la fonction foo devrait en fait ressembler à ceci : foo (x, y), mais on sait que les paramètres de la fonction sont en réalité contraints par la fonction, c'est-à-dire que la vraie variable libre n'est que x.
Cela peut conduire à une définition simple, Dans une fonction, s'il existe une variable qui n'est ni une variable locale ni un paramètre formel, on peut la considérer comme formant une fermeture.

D'où viennent les variables libres ?

Dans presque toutes les langues, les variables portant le même nom sont recherchées à proximité. Tout d'abord, elles sont recherchées dans cette portée. Si elles ne la trouvent pas, elles vont dans la portée parent. Nous appelons cela une chaîne de portée.
Dans une fonction de fermeture, les variables libres sont généralement fournies par le parent. Regardez l'exemple suivant :


function foo(x) {
    var tmp = 3;
    function bar(y) {
        console.log(x + y + (++tmp));
    }
    bar(10);}foo(2)

Selon notre définition ci-dessus, bar a des variables libres et est une fermeture, mais pas foo.
Alors, comment pouvons-nous faire de foto une clôture ?


var x = 0;function foo() {
    var tmp = 3;
    function bar(y) {
        console.log(x + y + (++tmp));
    }
    bar(10);}// 其实转换一下,形如function foo2() {
    var tmp = 3;
    //function bar(y) {
        console.log(x + 10 + (++tmp));
    //}
    // bar(10);}

À ce stade, foo peut être considéré comme une fermeture.
À ce stade, certains amis peuvent penser que c'est différent des fermetures js que nous voyons habituellement. Les fermetures que nous voyons habituellement sont comme ceci : l'exemple vient de ce blog


.
function foo(x) {
    var tmp = new Number(3);
    return function (y) {
        alert(x + y + (++tmp));
    }}var bar = foo(2); // bar 现在是一个闭包bar(10);

Cette fonction peut en fait être réécrite comme suit :


bar = function (y) {
    // foo(2)
    alert(2 + y + (++tmp))}

Evidemment, tmp est une variable libre, qui est conforme à notre définition originale, bar est une fonction avec des variables libres.
Alors, où existe-t-il tmp ?
Lorsque foo(2) est exécuté, une variable avec tmp=3 sera générée. Cette variable est référencée par la fonction return, elle ne sera donc pas recyclée. Les variables libres dans la fonction de retour trouvent des valeurs en fonction de la chaîne de portée. La fonction bar est définie dans foo(2), donc la variable tmp est d'abord recherchée dans la zone variable de foo(2) et utilisée.

Remarque : concernant la question de la chaîne de portée, je l'analyserai dans le prochain article.

En parlant de ça, insérez le mode module.

Mode module pour l'utilisation de la fermeture


var Module = (function () {
    var aaa = 0;
    var foo = function () {
        console.log(aaa);
    }
    
    return {
        Foo: foo    }})();// 或者(function () {
    var aaa = 0;
    var foo = function () {
        console.log(aaa);
    }
    
    window.Module = {
        Foo: foo    }})();

Notez les deux exemples ci-dessus, le module lui-même n'est qu'un objet, mais la fonction de retour elle-même forme des fermetures assurez-vous que la portée est propre et ne polluera pas d'autres fonctions.

En parlant de ça, certains amis doivent penser qu'il s'agit d'une catégorie alternative ? Avoir des variables locales et des fonctions accessibles. Oui, en termes d'apparence, je pense que les fermetures et les classes sont très similaires.

Classe

Prenons Java comme exemple :


class Foo {    
    private int a;    
    int Say( int b ) {        
    return a + b; 
    }  
}

Dans le Foo ci-dessus, le a dans la fonction Say est en dehors du la fonction scope , est une variable libre. Say peut être considéré comme formant une fermeture de fonction. Mais la différence avec js est que les méthodes d'instance doivent être appelées via des instances de classes, c'est-à-dire des objets.
Dans la conception de Java, les droits d'accès, privés, de protection, par défaut et de package sont clairement définis, ce qui constitue un travail pionnier dans la standardisation des appels. Cela fait également que les programmeurs Java envisagent rarement l'implémentation de fermetures, car les variables et les fonctions ont des mots-clés pour définir les autorisations d'accès et appartiennent à chaque classe, ce qui est clair et clair.

Inconvénients des fermetures

Si vous comprenez les fermetures en termes de mise en œuvre de classe, il est facile de comprendre pourquoi il n'est pas recommandé d'utiliser des fermetures.
Chaque fois qu'une fermeture est appelée, une portée sera générée pour stocker certaines variables libres requises par la fonction de fermeture. Cela peut facilement entraîner un gaspillage de mémoire. Même en programmation Java, il n'est pas recommandé de créer de nouveaux objets avec désinvolture.

Digression

Dans l'article précédent lier, appeler, appliquer, j'ai mentionné un point, Parce qu'il est orienté objet, il est nécessaire de lier cela.
Concernant l'orienté objet, je pense que l'avantage de l'orienté objet est qu'il est facile à comprendre, à maintenir et à réutiliser. Cela dépasse de loin les exigences de performances lorsque plusieurs personnes développent de grands projets.
Même maintenant que la loi de Moore ralentit, la mémoire est très bon marché par rapport à avant, les exigences de performances sont donc extrêmes depuis l'Antiquité, et désormais la lisibilité du code est généralement préconisée.
Il y a des super experts qui ont créé ce monde coloré de code. Afin de permettre à plus de gens de découvrir le plaisir de la programmation, ils ont conçu des langages de programmation plus faciles à comprendre et inventé divers compilateurs et analyseurs...
Si vous écrivez simplement un programme 1+1, il n'est pas nécessaire d'être orienté objet. Si les humains peuvent avoir une logique et une mémoire super puissantes avec les machines, il n'est pas nécessaire d'être orienté objet.

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!

Déclaration:
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