Maison >interface Web >js tutoriel >Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS
Cet article vous apporte des connaissances pertinentes sur javascript, qui présente principalement les problèmes liés à la façon dont le moteur js exécute le code js. Lorsque le moteur js exécute le code js, il effectuera également une analyse lexicale et une analyse grammaticale de haut en bas. , l'analyse sémantique et d'autres traitements, et générer AST une fois l'analyse du code terminée, j'espère que cela sera utile à tout le monde.
Recommandations associées : Tutoriel Javascript
Nous entendons probablement souvent "environnement d'exécution", "portée", "prototype (chaîne)", "contexte d'exécution", etc. Que décrivent-ils ?
Nous savons que js est un langage faiblement typé et que le type de variable n'est déterminé qu'au moment de l'exécution. Lorsque le moteur js exécute le code js, il effectuera également une analyse lexicale, analyse grammaticale, analyse sémantique et d'autres processus de haut en bas, et générera un AST (arbre de syntaxe abstraite) une fois l'analyse du code terminée. , et enfin le générer sur la base du code AST Machine que le CPU peut exécuter et exécuter.
De plus, le moteur JS effectuera également d'autres traitements lors de l'exécution du code. Par exemple, il y a deux étapes dans la V8 :
Cela conduit à deux concepts : « contexte d'exécution » et « chaîne de portée ».
D'après ce qui précède, nous pouvons savoir : lorsque le code js exécute un morceau de code exécutable, un contexte d'exécution correspondant sera créé.
Tout d'abord, il existe une notion correspondant au code exécutable en js : "environnement d'exécution" - environnement global, environnement de fonction et eval
.
Deuxièmement, pour chaque contexte d'exécution, il existe trois propriétés importantes :
Regardons deux morceaux de code :
var Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS="global Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS";function checkCompréhension approfondie de la façon dont le moteur JavaScript exécute le code JS(){ var Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS="local Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS"; function f(){ return Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS; } return f();}checkCompréhension approfondie de la façon dont le moteur JavaScript exécute le code JS();
var Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS="global Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS";function checkCompréhension approfondie de la façon dont le moteur JavaScript exécute le code JS(){ var Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS="local Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS"; function f(){ return Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS; } return f;}checkCompréhension approfondie de la façon dont le moteur JavaScript exécute le code JS()();
Ils imprimeront What ?
Pourquoi ? La réponse est que leurs piles de contextes d’exécution sont différentes !
Qu'est-ce que la « pile de contexte d'exécution » ?
Lors de l'exécution d'un code exécutable, des préparations seront faites à l'avance. Le « travail de préparation » est ici professionnellement appelé « contexte d'exécution ». Mais avec l’augmentation du code exécutable comme les fonctions, comment gérer autant de contextes d’exécution ? Le moteur JS a donc créé le concept de pile de contexte d'exécution.
On peut tout à fait utiliser un tableau pour simuler son comportement (il y a toujours un contexte d'exécution global globalContext en bas de la pile)
On définit un EStack, d'abord
EStack=[globalContext];
puis simule le premier bout de code :
EStack.push(<checkcompr approfondie de la fa dont le moteur javascript ex code js> functionContext);EStack.push(<f> functionContext);EStack.pop();EStack.pop();</f></checkcompr>
Et le deuxième morceau de code est comme ceci :
EStack.push(<checkcompr approfondie de la fa dont le moteur javascript ex code js> functionContext);EStack.pop();EStack.push(<f> functionContext);EStack.pop();</f></checkcompr>
La raison est que vous devrez peut-être d'abord étudier le concept de « fermeture » !
Au fait, comment implémenter la « sauvegarde des données pendant longtemps » dans la « modularisation front-end » ?
Mise en cache ? Non. Fermeture!
Tout d'abord, la portée fait référence à la zone du programme où les variables sont définies. La portée spécifie comment trouver la variable, qui détermine les droits d'accès du code en cours d'exécution à la variable.
Il existe deux types de Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS : Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS statique et portée dynamique.
La portée statique adoptée par JS est également appelée « portée lexicale ». La portée d'une fonction est déterminée lorsque la fonction est définie.
D'après ce qui précède, les variables de la portée lexicale auront une certaine portée pendant le processus de compilation. Cette portée est le « contexte d’exécution actuel ». Après ES5, nous utilisons « environnement lexical » au lieu de portée pour décrire le contexte d'exécution. L'environnement lexical se compose de deux membres :
Nous sommes toujours là Regardez un exemple :
var Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS=1;function foo(){ console.log(Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS);}function bar(){ var Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS=2; foo();}bar();
En regardant la définition ci-dessus, que faut-il imprimer ?
Analysons le processus d'exécution :
Exécutez la fonction foo(), recherchez d'abord s'il y a une valeur de variable locale à l'intérieur de la fonction foo. Sinon, recherchera le code sur la couche supérieure en fonction de la position où il a été défini, c'est-à-dire valeur = 1. Le résultat sera donc imprimé comme 1.
Bien sûr, ce n'est pas si simple et peut être résumé. Vous pouvez l'analyser du point de vue du contexte d'exécution.
上面我们说了词法环境(作用域)的两个组成。再结合执行上下文,我们不难发现:通过外部词法环境的引用,作用域可以顺着栈层层拓展,建立起从当前环境向外延伸的一条链式结构。
再来看一个例子:
function foo(){ console.dir(bar); var a=1; function bar(){ a=2; }}console.dir(foo);foo();
由静态作用域,全局函数foo创建了一个自身对象的 [[Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS]]
属性
foo[[Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS]]=[globalContext];
而当我们执行foo()时,也会先后进入foo函数的定义期和执行期。在foo函数的定义期时,函数bar的 [[Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS]]
将会包含全局内置Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS和foo的内置Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS
bar[[Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS]]=[fooContext,globalContext];
这证明了这一点:“JS会通过外部词法环境引用来创建变量对象的一个作用域链,从而保证对执行环境有权访问的变量和函数的有序访问。”
让我们再回头看看执行上下文中的那道题,在前面我们说了它们有什么不同,这里说下为什么它们相同地打印了“local Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS”:还是那句话“JS采用的是词法作用域,函数的作用域取决于函数创建的位置” —— JS函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量Compréhension approfondie de la façon dont le moteur JavaScript exécute le code JS一定是指局部变量,不管何时何地执行 f() ,这种绑定在执行 f() 时依然有效。
当某个变量无法在自身词法环境记录中找到时,可以根据外部词法环境引用向外层进行寻找,直到最外层的词法环境中外部词法环境引用为null
。
与此相似的是“对象中基于原型链的查找”:
__proto__
为null)为止它们的区别也显而易见:原型链是通过 prototype 属性建立对象继承的链接;而作用域链是指内部函数能访问到外部函数的闭包。不管直接还是间接,所有函数的作用域链最终都链接到全局上下文。
相关推荐: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!