


Introduction détaillée à JavaScript de la définition à l'exécution, ce que tous les programmeurs devraient savoir
De la définition à l'exécution de JavaScript, le moteur JS effectue beaucoup de travail d'initialisation au niveau de la couche d'implémentation. Par conséquent, avant d'apprendre le mécanisme de fonctionnement du moteur JS, nous devons introduire plusieurs concepts connexes : pile d'environnement d'exécution, objet global, environnement d'exécution, objets variables, objets actifs, portées et chaînes de portée, etc. Ces concepts sont les composants centraux du moteur JS. Le but de cet article n'est pas de vous expliquer chaque concept isolément, mais d'utiliser une démo simple pour effectuer une analyse et expliquer de manière exhaustive chaque détail du moteur JS, de la définition à l'exécution, ainsi que le rôle que ces concepts y jouent.
var x = 1; //定义一个全局变量 x function A(y){ var x = 2; //定义一个局部变量 x function B(z){ //定义一个内部函数 B console.log(x+y+z); } return B; //返回函数B的引用 } var C = A(1); //执行A,返回B C(1); //执行函数B
Cette démo est une fermeture, le résultat de l'exécution est 4, en dessous nous Le mécanisme de fonctionnement du moteur JS sera analysé en trois étapes : initialisation globale, fonction d'exécution A et fonction d'exécution B :
1. Initialisation globale
Lorsque le moteur JS saisit un morceau de code exécutable, il doit effectuer les trois tâches d'initialisation suivantes :
Tout d'abord, créez un objet global (Global Object There is). une seule copie de cet objet au niveau mondial, ses propriétés sont accessibles de partout, et son existence accompagne tout le cycle de vie de l'application. Lorsque l'objet global est créé, les objets JS couramment utilisés tels que Math, String, Date et document sont utilisés comme attributs. Étant donné que cet objet global n'est pas accessible directement par son nom, il existe une autre fenêtre d'attributs et window est pointée vers elle-même, de sorte que l'objet global soit accessible via window. La structure générale de l'objet global simulé avec du pseudo code est la suivante :
//创建一个全局对象 var globalObject = { Math:{}, String:{}, Date:{}, document:{}, //DOM操作 ... window:this //让window属性指向了自身 }
Ensuite, le moteur JS doit construire une pile d'environnement d'exécution (Execution Context Stack), avec ceci Dans le même temps, un environnement d'exécution global (Execution Context) EC doit également être créé et poussé dans la pile d'environnement d'exécution. La fonction de la pile d'environnement d'exécution est de garantir que le programme peut être exécuté dans le bon ordre. En JavaScript, chaque fonction possède son propre environnement d'exécution. Lorsqu'une fonction est exécutée, l'environnement d'exécution de la fonction sera poussé en haut de la pile de l'environnement d'exécution et obtiendra les droits d'exécution. Lorsque la fonction termine son exécution, son environnement d'exécution est supprimé du haut de la pile et les droits d'exécution sont renvoyés à l'environnement d'exécution précédent. Nous utilisons du pseudocode pour simuler la relation entre la pile de l'environnement d'exécution et EC :
var ECStack = []; //定义一个执行环境栈,类似于数组 var EC = {}; //创建一个执行空间, //ECMA-262规范并没有对EC的数据结构做明确的定义,你可以理解为在内存中分配的一块空间 ECStack.push(EC); //进入函数,压入执行环境 ECStack.pop(EC); //函数返回后,删除执行环境
Enfin, le moteur JS crée également un objet variable globale associé à EC (Varibale Object) VO, et le point VO vers l'objet global VO contient non seulement les propriétés d'origine de l'objet global, mais inclut également la variable x définie globalement et la fonction A. En même temps, lors de la définition de la fonction A, elle également. include A ajoute une portée d'attribut interne et pointe la portée vers VO. Lorsque chaque fonction est définie, un attribut de portée qui lui est associé est créé. La portée pointe toujours vers l'environnement dans lequel la fonction est définie. La structure ECStack à l'heure actuelle est la suivante :
ECStack = [ //执行环境栈 EC(G) = { //全局执行环境 VO(G):{ //定义全局变量对象 ... //包含全局对象原有的属性 x = 1; //定义变量x A = function(){...}; //定义函数A A[[scope]] = this; //定义A的scope,并赋值为VO本身 } } ];
2. Fonction d'exécution A
Lorsque l'exécution entre A(1), le moteur JS Le travail suivant doit être effectué :
Tout d'abord, le moteur JS créera l'environnement d'exécution EC de la fonction A, puis l'EC est poussé en haut de la pile de l'environnement d'exécution et obtient les droits d'exécution . À l'heure actuelle, il existe deux environnements d'exécution dans la pile d'environnement d'exécution, à savoir l'environnement d'exécution global et l'environnement d'exécution de la fonction A. L'environnement d'exécution de A est en haut de la pile et l'environnement d'exécution global est en bas. de la pile. Ensuite, créez la chaîne de portées (Scope Chain) de la fonction A. En JavaScript, chaque environnement d'exécution possède sa propre chaîne de portées pour la résolution des identifiants. Lorsque l'environnement d'exécution est créé, sa chaîne de portées est initialisée. de la fonction en cours d'exécution.
Ensuite, le moteur JS créera un objet d'activation (Activation Object) AO de la fonction actuelle. L'objet d'activité joue ici le rôle d'un objet variable, mais son nom est différent dans la fonction (on peut le penser). d'un objet variable est un concept général, et l'objet actif en est une branche), AO contient les paramètres formels de la fonction, l'objet arguments, cet objet, et la définition des variables locales et des fonctions internes, puis l'AO sera poussé dans le haut de la chaîne de lunette. Il convient de noter que lors de la définition de la fonction B, le moteur JS ajoutera également un attribut de portée à B et pointera la portée vers l'environnement dans lequel la fonction B est définie. L'environnement dans lequel la fonction B est définie est l'objet actif AO de A. AO est situé à l’avant de la liste chaînée Puisque la liste chaînée est connectée bout à bout, la portée de la fonction B pointe vers toute la chaîne de portée de A. Jetons un coup d'œil à la structure ECStack à ce moment :
ECStack = [ //执行环境栈 EC(A) = { //A的执行环境 [scope]:VO(G), //VO是全局变量对象 AO(A) : { //创建函数A的活动对象 y:1, x:2, //定义局部变量x B:function(){...}, //定义函数B B[[scope]] = this; //this指代AO本身,而AO位于scopeChain的顶端,因此B[[scope]]指向整个作用域链 arguments:[],//平时我们在函数中访问的arguments就是AO中的arguments this:window //函数中的this指向调用者window对象 }, scopeChain:<AO(A),A[[scope]]> //链表初始化为A[[scope]],然后再把AO加入该作用域链的顶端,此时A的作用域链:AO(A)->VO(G) }, EC(G) = { //全局执行环境 VO(G):{ //创建全局变量对象 ... //包含全局对象原有的属性 x = 1; //定义变量x A = function(){...}; //定义函数A A[[scope]] = this; //定义A的scope,A[[scope]] == VO(G) } } ];
3.Exécuter la fonction B
Après l'exécution de la fonction A, il renvoie La référence de B est affectée à la variable C. Exécuter C(1) équivaut à exécuter B(1) Le moteur JS doit effectuer le travail suivant :
.首先,还和上面一样,创建函数B的执行环境EC,然后EC推入执行环境栈的顶部并获取执行权。 此时执行环境栈中有两个执行环境,分别是全局执行环境和函数B的执行环境,B的执行环境在栈顶,全局执行环境在栈的底部。(注意:当函数A返回后,A的执行环境就会从栈中被删除,只留下全局执行环境)然后,创建函数B的作用域链,并初始化为函数B的scope所包含的对象,即包含了A的作用域链。最后,创建函数B的活动对象AO,并将B的形参z, arguments对象 和 this对象作为AO的属性。此时ECStack将会变成这样:
ECStack = [ //执行环境栈 EC(B) = { //创建B的执行环境,并处于作用域链的顶端 [scope]:AO(A), //指向函数A的作用域链,AO(A)->VO(G) var AO(B) = { //创建函数B的活动对象 z:1, arguments:[], this:window } scopeChain:<AO(B),B[[scope]]> //链表初始化为B[[scope]],再将AO(B)加入链表表头,此时B的作用域链:AO(B)->AO(A)-VO(G) }, EC(A), //A的执行环境已经从栈顶被删除, EC(G) = { //全局执行环境 VO:{ //定义全局变量对象 ... //包含全局对象原有的属性 x = 1; //定义变量x A = function(){...}; //定义函数A A[[scope]] = this; //定义A的scope,A[[scope]] == VO(G) } } ];
当函数B执行“x+y+z”时,需要对x、y、z 三个标识符进行一一解析,解析过程遵守变量查找规则:先查找自己的活动对象中是否存在该属性,如果存在,则停止查找并返回;如果不存在,继续沿着其作用域链从顶端依次查找,直到找到为止,如果整个作用域链上都未找到该变量,则返回“undefined”。从上面的分析可以看出函数B的作用域链是这样的:
AO(B)->AO(A)->VO(G)
因此,变量x会在AO(A)中被找到,而不会查找VO(G)中的x,变量y也会在AO(A)中被找到,变量z 在自身的AO(B)中就找到了。所以执行结果:2+1+1=4.
简单的总结语
了解了JS引擎的工作机制之后,我们不能只停留在理解概念的层面,而要将其作为基础工具,用以优化和改善我们在实际工作中的代码,提高执行效率,产生实际价值才是我们的真正目的。就拿变量查找机制来说,如果你的代码嵌套很深,每引用一次全局变量,JS引擎就要查找整个作用域链,比如处于作用域链的最底端window和document对象就存在这个问题,因此我们围绕这个问题可以做很多性能优化的工作,当然还有其他方面的优化,此处不再赘述,本文仅当作抛砖引玉吧!
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)

Comment utiliser WebSocket et JavaScript pour mettre en œuvre un système de reconnaissance vocale en ligne Introduction : Avec le développement continu de la technologie, la technologie de reconnaissance vocale est devenue une partie importante du domaine de l'intelligence artificielle. Le système de reconnaissance vocale en ligne basé sur WebSocket et JavaScript présente les caractéristiques d'une faible latence, d'un temps réel et d'une multiplateforme, et est devenu une solution largement utilisée. Cet article explique comment utiliser WebSocket et JavaScript pour implémenter un système de reconnaissance vocale en ligne.

WebSocket et JavaScript : technologies clés pour réaliser des systèmes de surveillance en temps réel Introduction : Avec le développement rapide de la technologie Internet, les systèmes de surveillance en temps réel ont été largement utilisés dans divers domaines. L'une des technologies clés pour réaliser une surveillance en temps réel est la combinaison de WebSocket et de JavaScript. Cet article présentera l'application de WebSocket et JavaScript dans les systèmes de surveillance en temps réel, donnera des exemples de code et expliquera leurs principes de mise en œuvre en détail. 1. Technologie WebSocket

"Explorer Discuz : définition, fonctions et exemples de code" Avec le développement rapide d'Internet, les forums communautaires sont devenus une plate-forme importante permettant aux gens d'obtenir des informations et d'échanger des opinions. Parmi les nombreux systèmes de forum communautaire, Discuz, en tant que logiciel de forum open source bien connu en Chine, est favorisé par la majorité des développeurs et administrateurs de sites Web. Alors, qu’est-ce que Discuz ? Quelles fonctions a-t-il et comment peut-il aider notre site Web ? Cet article présentera Discuz en détail et joindra des exemples de code spécifiques pour aider les lecteurs à en savoir plus.

La clé primaire composite dans MySQL fait référence à la clé primaire composée de plusieurs champs dans la table, qui est utilisée pour identifier de manière unique chaque enregistrement. Contrairement à une clé primaire unique, une clé primaire composite est formée en combinant les valeurs de plusieurs champs. Lors de la création d'une table, vous pouvez définir une clé primaire composite en spécifiant plusieurs champs comme clés primaires. Afin de démontrer la définition et la fonction des clés primaires composites, nous créons d'abord une table nommée utilisateurs, qui contient trois champs : id, nom d'utilisateur et email, où id est une clé primaire et un utilisateur auto-incrémentés.

Introduction à l'interface PHP et à sa définition. PHP est un langage de script open source largement utilisé dans le développement Web. Il est flexible, simple et puissant. En PHP, une interface est un outil qui définit des méthodes communes entre plusieurs classes, réalisant le polymorphisme et rendant le code plus flexible et réutilisable. Cet article présentera le concept des interfaces PHP et comment les définir, et fournira des exemples de code spécifiques pour démontrer leur utilisation. 1. Concept d'interface PHP L'interface joue un rôle important dans la programmation orientée objet, définissant l'application de classe

JavaScript et WebSocket : Construire un système efficace de prévisions météorologiques en temps réel Introduction : Aujourd'hui, la précision des prévisions météorologiques revêt une grande importance pour la vie quotidienne et la prise de décision. À mesure que la technologie évolue, nous pouvons fournir des prévisions météorologiques plus précises et plus fiables en obtenant des données météorologiques en temps réel. Dans cet article, nous apprendrons comment utiliser la technologie JavaScript et WebSocket pour créer un système efficace de prévisions météorologiques en temps réel. Cet article démontrera le processus de mise en œuvre à travers des exemples de code spécifiques. Nous

Tutoriel JavaScript : Comment obtenir le code d'état HTTP, des exemples de code spécifiques sont requis Préface : Dans le développement Web, l'interaction des données avec le serveur est souvent impliquée. Lors de la communication avec le serveur, nous devons souvent obtenir le code d'état HTTP renvoyé pour déterminer si l'opération a réussi et effectuer le traitement correspondant en fonction de différents codes d'état. Cet article vous apprendra comment utiliser JavaScript pour obtenir des codes d'état HTTP et fournira quelques exemples de codes pratiques. Utilisation de XMLHttpRequest

Que sont les caractères pleine chasse ? Dans les systèmes de codage informatique, les caractères double largeur sont une méthode de codage de caractères qui occupe deux positions de caractères standard. De manière correspondante, la méthode de codage de caractères qui occupe une position de caractère standard est appelée caractère demi-chasse. Les caractères pleine chasse sont généralement utilisés pour la saisie, l'affichage et l'impression de caractères chinois, japonais, coréens et autres caractères asiatiques. Dans les méthodes de saisie et d'édition de texte chinoises, les scénarios d'utilisation des caractères pleine chasse et des caractères demi-chasse sont différents. Utilisation de caractères pleine chasse Méthode de saisie chinoise : Dans la méthode de saisie chinoise, les caractères pleine chasse sont généralement utilisés pour saisir des caractères chinois, tels que des caractères chinois, des symboles, etc.
