Récemment, je relire "JavaScript Advanced Programming 3" et je pense que je devrais écrire des blogs pour enregistrer certaines des connaissances que j'ai apprises, sinon je l'oublierai. Ce que je veux résumer aujourd'hui, c'est l'environnement d'exécution JS et la portée.
Tout d'abord, parlons de l'environnement d'exécution
1. Environnement d'exécution
Le concept dans le livre, l'environnement d'exécution définit d'autres données auxquelles les variables ou les fonctions ont accès et détermine leurs comportements respectifs. Chaque environnement d'exécution a un objet variable qui lui est associé. Toutes les variables et fonctions définies dans l'environnement sont stockées dans cet objet. Bien que nous ne puissions pas accéder à cet objet lors de la rédaction de code, l'analyseur l'utilisera dans l'arrière-plan lors du traitement des données.
L'environnement d'exécution est un concept, un mécanisme qui définit si une variable ou une fonction a la permission d'accéder à d'autres données
Dans JavaScript, le code JavaScript exécutable est divisé en trois types:
1. Code global, c'est-à-dire le code global qui n'est dans aucune fonction, tel que: un fichier JS, du code JS intégré dans les pages HTML, etc.
2.
3. Code de fonction, c'est-à-dire le code JS du corps de fonction dans les fonctions définies par l'utilisateur.
Sautez le code EVAL et ne parlez que de l'environnement d'exécution global et de l'environnement d'exécution de la fonction.
1. Environnement mondial:
L'environnement mondial est l'environnement d'exécution le plus périphérique. L'environnement d'exécution global est considéré comme un objet de fenêtre. Par conséquent, toutes les variables et fonctions globales sont créées en tant que propriétés et méthodes des objets de fenêtre. Lorsque le code est chargé dans le navigateur, l'environnement d'exécution globale est créé (l'environnement d'exécution globale n'est détruit que lorsque nous fermons la page Web ou le navigateur). Par exemple, dans une page, créez un environnement d'exécution global lorsque le code JS est chargé pour la première fois.
C'est aussi pourquoi les fermetures ont un désavantage de fuite de mémoire. Parce que les fonctions externes dans les fermetures sont traitées comme un environnement mondial. Il ne sera donc pas détruit et sera conservé en mémoire.
2. Environnement d'exécution de la fonction
Chaque fonction a son propre environnement d'exécution. Lorsque l'exécution entre une fonction, l'environnement d'exécution de la fonction sera poussé vers le haut d'une pile d'environnement d'exécution et obtiendra des droits d'exécution. Lorsque cette fonction est exécutée, son environnement d'exécution est supprimé du haut de la pile et le droit d'exécution est renvoyé à l'environnement d'exécution précédent. Il s'agit du flux d'exécution dans le programme ECMAScript.
Il peut également être interprété de cette manière: lorsqu'une fonction JavaScript est appelée, la fonction entrera dans l'environnement d'exécution correspondant à la fonction. Si une autre fonction est appelée, un nouvel environnement d'exécution est créé et le processus d'exécution se trouve dans cet environnement pendant l'appel de fonction. Lorsque la fonction appelée revient, le processus d'exécution revient à l'environnement d'exécution d'origine. Par conséquent, l'exécution du code JavaScript forme une pile d'environnement d'exécution.
Lorsqu'une fonction est appelée, l'environnement local de la fonction est créé (après l'exécution du code de la fonction, l'environnement est détruit et que toutes les variables et définitions de fonction stockées dedans sont également détruites).
Période de définition 2-1
Lorsqu'une fonction est définie, un attribut [[SCOPE]] sera créé. Cet objet correspond à une liste d'objets. Les objets de la liste ne peuvent être accessibles qu'en interne par JavaScript et ne sont pas accessibles par syntaxe.
(La portée signifie la portée.)
Nous définissons une fonction globale a, puis la fonction a crée un attribut A [[SPOCE]]. À l'heure actuelle, [[SCOPE]] ne contient que l'objet global [objet global].
Si nous définissons une fonction B à l'intérieur de A, alors la fonction B créera également un attribut [[SCOPE]]. L'attribut [[SPOCE]] de B contient deux objets, l'un est l'objet d'activation actif de l'objet actif A et l'autre est l'objet global. L'objet actif de A est devant et l'objet global est à l'arrière.
En bref, l'ordre de la liste d'objets dans la propriété [SCOPE] d'une fonction est l'objet d'objet d'activation de la couche de fonction précédente, puis la couche supérieure, jusqu'à l'objet global le plus extérieur.
Voici l'exemple de code: A n'a qu'une seule portée, B a deux portées
// fonction de fonction externe a () {var someVar; // Fonction de fonction interne B () {var someVar; }}2-2 Période d'exécution
Lorsqu'une fonction est exécutée, elle entre dans l'environnement d'exécution de la fonction. Tout d'abord, il crée son propre objet actif [objet d'activation] (cet objet contient la définition de ceci, les arguments, les variables locales (y compris les paramètres nommés) et une chaîne de portée d'un objet variable. Ensuite, copiez l'objet actif au sommet de [[la chaîne de portée]. objets qui ont la permission d'accéder à l'environnement d'exécution.
// La première étape consiste à créer l'environnement d'exécution global. Contexte d'exécution globale et objets d'activité globale. // Définissez la [[portée]] globale, qui ne contient que des objets de fenêtre // scanne les variables de définition globale et les objets de fonction: Color 【Undefined】, ChangeColor 【FD crée ChangeColor [[SCOPE]], qui ne contient que des objets d'activité globale], qui sont ajoutés à la fenêtre, donc les variables globales et les objets de fonction globale sont définis comme des properties de la fenêtre. // Le programme a été défini afin que ChangeColor () puisse être exécuté n'importe où dans cet environnement d'exécution. La couleur a également été définie, mais sa valeur n'est pas définie // La deuxième étape est la couleur qui attribue "bleu" var color = "blue"; // il ne nécessite pas d'attribution, il se réfère à sa propre fonction ChangeColor () {// La quatrième étape entre dans l'environnement d'exécution de ChangEColor // Copier le changlecolor [[Scope] vers la chaîne de la lune Un autrecolor 【Undefined】 et swapcolors 【FD crée les swapcolors [[Scope]] et ajoutent les objets actifs et les objets actifs globaux】 aux objets actifs, et ajoutent également des arguments et ce // les objets actifs poussent dans la chaîne de portée // Le programme a été défini, donc SwapColors () peut être exécuté n'importe où dans cet environnement d'exécution. Un autrecolor a été défini, mais sa valeur n'est pas définie // La cinquième autre affectation "Red" var AnotherColor = "Red"; // Il ne nécessite pas d'attribution, il fait référence à sa propre fonction swapColors () {// étape 7 entrez l'environnement d'exécution de SwapColors et créez son objet actif // Copier les swapcoles '[[Scope]] pour étendre la chaîne // scanne pour définir les variables et définir des objets de fonction, ajouter des variables Tempcolor 【UNDEFINE Valeur d'attribution temporaire d'un autrecolor, d'un autrecolor et d'une couleur se trouvera le long de la chaîne de portée, et continuera d'exécuter var tempcolor = un autrecolor; un autrecolor = couleur; color = tempcolor; } // Étape 6: Exécuter SwapColors et entrez son environnement d'exécution swapColors ();} // Étape 3: Exécutez ChangeColor et entrez dans son environnement d'exécution ChangeColor ();2-3 Identifiant d'accès:
Lorsqu'un identifiant est rencontré lors de l'exécution du code JS, il recherchera dans la chaîne de portée du contexte d'exécution (contexte d'exécution) en fonction du nom de l'identifiant. À partir du premier objet de la chaîne de portée (l'objet d'activation de la fonction), s'il n'est pas trouvé, recherchez l'objet suivant dans la chaîne de portée et répétez jusqu'à ce que la définition de l'identifiant soit trouvée. Si le dernier objet de la portée n'est pas trouvé après la recherche de la recherche, c'est-à-dire l'objet global (objet global), une erreur sera lancée, ce qui incite non défini.
2. Chaîne de portée / portée (chaîne de portée / portée)
Lorsque le code est exécuté dans un environnement, une chaîne de portée est créée. Le but de la chaîne de portée est d'assurer l'accès ordonné à toutes les variables et fonctions qui ont la permission d'accéder à l'environnement d'exécution. L'ensemble de la chaîne de portée est une liste liée construite par des objets variables à différents emplacements d'exécution selon les règles. L'extrémité avant de la chaîne de portée est toujours l'objet variable dans l'environnement où se trouve le code actuellement exécuté.
Si cet environnement est une fonction, son objet d'activation est utilisé comme objet variable. L'objet actif ne contient qu'une seule variable au début, qui est l'objet d'arguments à l'intérieur de la fonction. L'objet variable suivant dans la chaîne de portée provient de l'environnement d'inclusion de la fonction, et l'objet variable suivant provient de l'environnement d'inclusion suivant. De cette façon, il continue vers l'environnement d'exécution global, et l'objet variable de l'environnement d'exécution global est toujours le dernier objet de la chaîne de portée.
Comme indiqué sur la figure:
Exemples dans le livre:
var color = "bleu"; function changEColor () {var autrementColor = "Red"; fonction swapColors () {var tempcolor = un autrecolor; un autrecolor = couleur; color = tempcolor; // TODO quelque chose} swapColors ();} ChangeColor (); // Tempcolor et l'anocolore ne sont pas accessibles ici; mais la couleur est accessible; alerte ("la couleur est maintenant" + couleur);Grâce à l'analyse ci-dessus, nous pouvons savoir que l'environnement interne peut accéder à tous les environnements externes via des chaînes de portée, mais l'environnement externe ne peut accéder à aucune variable et fonction dans l'environnement interne.
Ces environnements sont linéaires et ordonnés. Chaque environnement peut rechercher des chaînes de portée vers le haut pour interroger les variables et les noms de fonction; Cependant, tout environnement ne peut pas entrer dans un autre environnement d'exécution en recherchant des chaînes de portée vers le bas.
Pour la fonction swapcolor () dans l'exemple ci-dessus, sa chaîne de portée comprend: objet variable swapcolor (), objet variable ChangColor () et objet global. L'environnement local de SwapColor () commence à rechercher des variables et des noms de fonction dans son propre objet variable. S'il ne peut être trouvé, recherchez la chaîne de portée de ChangeColor vers le haut. . . . . Et ainsi de suite. Cependant, la fonction ChangeColor () ne peut pas accéder aux variables dans Swapcolor
Révélation: essayez d'utiliser des variables locales pour réduire le temps de recherche
1. Aucune portée au niveau du bloc
Contrairement à C, C ++ et Java, JavaScript n'a pas de portée au niveau du bloc. Regardez le code suivant:
if (true) {var myvar = "zhang san"; } alerte (myvar); // zhang sanS'il y a une portée au niveau du bloc, MyVar ne peut pas être accessible de l'extérieur. Regardez ce qui suit
pour (var i = 0; i <10; i ++) {console.log (i)} alert (i); // 10Pour les langues avec une portée au niveau du bloc, comme le code Java ou C #, I est une variable initialisée pour et ne peut être accessible à l'extérieur. Parce que je n'existe que dans le poids de la boucle pour, après avoir exécuté la boucle pour, toutes les variables dans le FOR sont détruites. Ce n'est pas le cas dans JavaScript. La déclaration variable pour FOR sera ajoutée à l'environnement d'exécution actuel (voici l'environnement d'exécution global). Par conséquent, une fois la boucle FOR terminée, la variable I existe toujours dans l'environnement d'exécution en dehors de la boucle. Par conséquent, 10 sera sorti.
2. Déclarer les variables
Lorsqu'une variable est déclarée en utilisant VAR, cette variable sera automatiquement ajoutée à l'environnement disponible le plus proche. Pour l'intérieur d'une fonction, l'environnement le plus proche est les variables locales de la fonction. Si la variable n'est pas initialisée, la variable est automatiquement ajoutée à la fonction globale.
Le code est le suivant:
var name = "xiao ming"; fonction getName () {alert (name); // 'Undefined' var name = 'xiao huang'; alerte (nom); // xiao huang} getName ()Pourquoi le prénom est-il indéfini? En effet, l'analyseur JavaScript entre dans un environnement d'exécution de fonction et analyse d'abord VAR et fonction.
Il équivaut à la promotion de la déclaration VAR ou fonction [Déclaration de fonction] en haut de l'environnement d'exécution.
En d'autres termes, lors de la saisie de notre fonction GetName, le mécanisme de recherche de l'identifiant trouve le VAR, et le nom est le nom de variable local, pas le nom global, car le nom de la fonction est promu en haut.
Le code ci-dessus sera analysé comme suit:
var name = "xiao ming"; fonction getName () {var name; alerte (nom); // 'Undefined' var name = 'xiao huang'; alerte (nom); // xiao huang} getName ()Étendre la chaîne de portée:
Bien qu'il n'y ait que deux types d'environnements d'exécution - portée globale et portée fonctionnelle, la chaîne de portée peut encore être étendue d'une manière ou d'une autre. Parce que certaines instructions peuvent ajouter un objet variable temporaire en haut de la chaîne de portée.
Il y a deux situations où cela se produit:
1. Le bloc de capture de l'instruction TRY-Catch;
2. Avec déclaration;
Ce qui précède concerne cet article. J'espère qu'il sera utile pour tout le monde d'apprendre et de comprendre l'environnement d'exécution JavaScript et la portée.