Maison  >  Article  >  interface Web  >  Un article sur le contexte d'exécution en Javascript

Un article sur le contexte d'exécution en Javascript

青灯夜游
青灯夜游avant
2023-02-14 19:41:062313parcourir

Cet article parlera du contexte d'exécution en Javascript et partagera une question de réflexion Grâce à l'analyse de la question de réflexion, vous aurez sûrement une compréhension plus approfondie du contexte d'exécution.

Un article sur le contexte d'exécution en Javascript

Dans les articles précédents, nous avons une compréhension approfondie des trois membres importants du contexte d'exécution : les objets variables, les chaînes de portée et ceci. Cet article est une collection et une agrégation du contenu des quatre premiers articles. . Réalisez une consolidation simple de points de connaissances dispersés. Je ne sais pas si quelqu'un est venu ici de l'article précédent. Notre dernier article a laissé une question grâce à l'analyse de la question, j'aurai une compréhension plus approfondie du contexte d'exécution.

Questions de réflexion

Afin de rendre le cas un peu plus compliqué, quelques modifications ont été apportées, mais les points examinés dans la question initiale n'ont pas été modifiés.

function func(value){
    getValue = function(){
        console.log(value);
    };
    return this
}
            
function getValue(){
    console.log(5);
}

Func(1).getValue(); //为什么是1呢?

Analyse d'exécution spécifique

Exécuter du code global, créer un contexte d'exécution global, le contexte global est poussé dans la pile de contexte d'exécution

ECStack = [ globalContext ];

Initialiser le contexte global

globalContext = {
    VO: {
        func: reference to function func(){},
        getValue: reference to function getValue(){}
    },
    Scope: [globalContext.VO],
    this: globalContext.VO //全局上下文
}

Initialiser le contexte global et créer deux fonctions à la en même temps, ils seront donc également enregistrés. Leur chaîne de portée parente se trouve dans leurs propriétés internes [[portée]]

func.[[scope]] = [
     globalContext.VO
];
getValue.[[scope]] = [
     globalContext.VO
];

Le code commence à s'exécuter à ce moment-là. Lorsque la dernière instruction est exécutée, la fonction func est exécutée en premier, ce qui crée. un contexte d'exécution de la fonction func étape par étape :

  • Copiez l'attribut de la fonction [[scope]] pour créer la chaîne de portée

  • Créez l'objet actif avec des arguments

  • Initialisez l'objet actif

  • Poussez l'objet actif en haut de la chaîne de portée checksfunccope.

  • Créez ceci, analyse simple : la valeur MemberExpression est func, func est un objet fonction, bien sûr une référence, où sa valeur de base est EnvironmentRecord, donc sa valeur est ImplicitThisValue (ref), et la valeur de retour est toujours indéfinie , en mode non strict, sa valeur sera implicitement convertie en objet global.

funcContext = {
    AO: {
        arguments: { // 数组
            0: 1,
            length: 1
        }
    },
    Scope: [AO, globalContext.VO],
    this: undefined
}

Certaines personnes peuvent avoir des questions, qu'en est-il de getValue in func ? , car il n'a pas de déclaration de variable, il s'agit donc en fait d'une opération d'affectation d'attribut, qui sera exécutée ultérieurement lors de l'exécution.

Créez le contexte d'exécution de la fonction et placez-le dans la pile de contexte d'exécution

    ECStack = [
        funcContext,
        globalContext
    ];

La fonction commence à s'exécuter. C'est la clé pour laquelle la sortie finale est 1 Dans la première phrase de l'opération d'affectation, vous devez trouver le. variable getValue le long du contexte d'exécution. , puis regardons la portée dans funcContext. Tout d'abord, nous trouvons funcContext.AO. Évidemment, l'attribut getValue n'existe pas. Ensuite, nous recherchons le long de la chaîne de portée, trouvons globalContext.VO et trouvons getValue. À ce stade, la réaffectation de l'attribut getValue sous la portée globale attribue une nouvelle version de la fonction, qui recrée la portée de la fonction et enregistre la chaîne de portée parent de cette nouvelle fonction getValue dans ses propriétés internes. ] À l'intérieur :

getValue .[[scope]] = [ funcContext.AO, globalContext.VO ];

Ensuite, continuez à renvoyer ceci, recherchez ceci dans funcContext, c'est-à-dire renvoiez un contexte d'exécution de fonction non défini ; le contexte d'exécution de la fonction apparaît de la pile

ECStack = [ globalContext ];

Continuez à exécuter Func(1).getValue() , la première moitié renvoie undefined À ce stade, le système se convertit implicitement en un objet variable globale et trouve l'attribut getValue à partir de l'objet variable globale. À cette époque, nous avons constaté que getValue n'était plus le garçon qu'il était à l'époque. Le contexte d'exécution de la fonction pour exécuter le nouveau getValue a été poussé sur la pile :

getValueContext = {
    AO: {
        arguments: { // 数组
            length: 0
        }
    },
    Scope: [ AO, funcContext.AO, globalContext.VO ],
    this: undefined
} ECStack = [
    getValueContext,
    globalContext
 ];
Func(1).getValue(),前半部分返回了 undefined ,此时系统隐式转换为全局变量对象,从全局变量对象中找到 getValue 属性。这时候我们发现 getValue 早已不是当年那个少年,执行全新的 getValue 的函数执行上下文并入栈:

rrreee

函数开始执行,发现她要输出 valueLa fonction a commencé à s'exécuter et a constaté qu'elle voulait afficher value, et je l'ai recherché le long de la portée. Il n'existe aucun attribut de ce type dans getValueContext.AO. Continuez la recherche pour trouver funcContext.AO (Attention !). , la valeur correspondante sera affichée et 1 sera affiché.

L'exécution de la fonction est terminée, getValueContext et globalContext sont retirés de la pile et détruits l'un après l'autre, et le code est terminé.

Résumé

Ce film utilise un exemple simple mais pas simple pour relier les quatre articles précédents afin d'analyser complètement le processus de travail du contexte d'exécution lorsque le code JS est exécuté. J'espère que tout le monde pourra comprendre cela plus profondément. . Cependant, je me demande si des étudiants attentifs ont découvert que dans l'exemple ci-dessus, lors de l'exécution de la fonction getValue, à partir de l'étape de recherche de la valeur de l'attribut (marquage de la position), à ce moment-là, la fonction func a évidemment été exécutée, et son contexte d'exécution a été publié, pourquoi pouvons-nous toujours trouver l'attribut value à partir de son contexte d'exécution ? Il s'agit en fait du principe de génération de fermeture. Dans le prochain article, nous utiliserons toujours cet exemple pour apprendre le principe de génération de fermeture.

【Apprentissage recommandé : Tutoriel avancé javascript

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer