Une plongée approfondie dans le module VM dans Node.js
Le module VM est le module principal de NodeJS. Il prend en charge la méthode require et le mécanisme de fonctionnement de NodeJS. Parfois, nous pouvons également utiliser des modèles de VM pour effectuer certaines choses spéciales. Cet article vous donnera une compréhension détaillée du module VM dans Node J'espère qu'il vous sera utile !
Référence machine virtuelle vm | Site officiel de Node
http://nodejs.cn/api/vm.html
Dans l'article précédent, nous avons mentionné un problème.
Comment une chaîne peut-elle être transformée en JS pour exécution ?
Nous avons présenté deux méthodes en détail, à savoir eval function et new Function.
Nous devons souligner à nouveau ici que les fonctions créées par le constructeur Function
ne créent pas de fermetures de l'environnement actuel. Elles sont toujours créées dans l'environnement global, elles ne sont donc accessibles qu'au moment de l'exécution. les variables et leurs propres variables locales ne peuvent pas accéder aux variables dans la portée dans laquelle elles ont été créées par le constructeur Function
. Ceci est cohérent avec l'utilisation du eval
Function
构造器创建的函数不会创建当前环境的闭包,它们总是被创建于全局环境,因此在运行时它们只能访问全局变量和自己的局部变量,不能访问它们被 Function
构造器创建时所在的作用域的变量。这一点与使用 eval
执行创建函数的代码不同。
global.a = 100; // 挂在到全局对象global上 var b = 200; // this !== global new Function("console.log(a)")() // 100 new Function("console.log(b)")() // b is not defined
Function
可以获取全局变量,所以他还是可能会有变量污染的情况出现。Function
是 模块引擎的实现原理 ,后续我会出一篇文章进行单独讲解。
还有一种解决方案,我们在上一次文章中没有进行详细的展开,那就是 vm
模块 。
vm模块
在上述文字中,我一直在强调一个概念,那就是 变量的污染。
VM的特点就是不受环境的影响,也可以说他就是一个 沙箱环境 (沙箱模式给模块提供一个环境运行而不影响其它模块和它们私有的沙箱)。
const vm = require('vm') global.a = 100; // 运行在当前环境中[当前作用域] vm.runInThisContext('console.log(a)'); // 100 // 运行在新的环境中[其他作用域] vm.runInNewContext('console.log(a)'); // a is not defined
在这里我们要强调一下,因为 在Node.js中全局变量是在多个模块下共享的,所以尽量不要在global中定义属性。 Demo中的定义是为了方便理解。
假设我们在同级目录下有一个文件 1.js ,里面定义了 global.a = 100;
。 现在我们引入这个文件
requrie(./1); console.log(a); // 100
我们可以发现,在当前文件中我们并没有定义变量a,仅仅只是把两个模块文件关联在了一起。这就是我上面提到的,Node中全局变量是在多个模块下共享的。
他的原理是因为在 Node 的环境中,全局中有一个执行上下文。
// 模拟一下Node的全局环境 // vm.runInThisContext在当前全局环境执行,但不会产生新函数 - function(exports, module, require, __dirname, __filename){ // ... } - vm.runInThisContext ... // vm.runInNewContext在全局环境之外执行 vm.runInNewContext ...
所以,vm.runInThisContext
可以访问到 global
上的全局变量,但是访问不到自定义的变量。而 vm.runInNewContext
访问不到 global
,也访问不到自定义变量,他存在于一个全新的执行上下文。
而我们require
就是通过 vm.runInThisContext
实现的。
实现require
主要可以分为以下四步。
读取需要引入的文件。
读取到文件后,将代码封装成一个函数。
通过
vm.runInThisContext
Le code qui exécute la fonction de création est différent.// 文件a通过module.exports导出一个变量,在文件b中使用require进行接收。 // a.js module.exports = "a" // b.js let a = require('./a'); console.log(a); // a
Copier après la connexion- moteur de module
. Je publierai un article pour l'expliquer séparément à l'avenir.
Il existe également une solution, que nous n'avons pas développée en détail dans le dernier article, et c'est le module
Fonction
peut obtenir des variables globales, elle peut donc toujours avoir une pollution variable. Fonction
est le principe d'implémentation du vm
. module vm
Dans le texte ci-dessus, j'ai mis l'accent sur un concept qui est la Pollution des variables. La caractéristique de la VM est qu'elle n'est pas affectée par l'environnement. On peut également dire qu'il s'agit d'un environnement sandbox (le mode Sandbox fournit un environnement permettant aux modules de s'exécuter sans affecter les autres modules et leurs bacs à sable privés. ).
let a = module.exports = "a";
Nous voulons souligner ici que parce que les variables globales dans
Node.js- sont partagées sous plusieurs modules, essayez donc de ne pas définir de propriétés dans global. Les définitions de la démo sont destinées à faciliter la compréhension.
Supposons que nous ayons un fichier 1.js dans le même répertoire, qui définit
global.a = 100;
. Maintenant que nous introduisons ce fichierlet a = (function(exports, module, require, __dirname, __filename){ module.exports = "a"; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
Copier après la connexionCopier après la connexionnous pouvons constater que nous ne définissons pas la variable a dans le fichier actuel, nous associons simplement les deux fichiers de module ensemble. C'est ce que j'ai mentionné ci-dessus, les variables globales dans Node sont partagées entre plusieurs modules.
La raison est que dans l'environnement de
Node , il existe un contexte d'exécution global. // a.js var a = 100; module.exports = function(){}
Copier après la connexionCopier après la connexionAinsi,
🎜L'implémentation devm.runInThisContext
peut accéder aux variables globales surglobal
, mais ne peut pas accéder aux variables personnalisées. Cependant,vm.runInNewContext
ne peut pas accéder àglobal
, ni aux variables personnalisées. Il existe dans un tout nouveau contexte d'exécution. Et notrerequire
est implémenté viavm.runInThisContext
.require
peut être divisée en quatre étapes suivantes. 🎜🎜🎜🎜Lisez les fichiers qui doivent être importés. 🎜🎜🎜🎜Après avoir lu le fichier, encapsulez le code dans une fonction. 🎜🎜🎜🎜Convertissez-le en syntaxe JS viavm.runInThisContext
. 🎜🎜🎜🎜Appel à code. 🎜🎜🎜🎜Supposons que nous ayons maintenant les deux fichiers suivants. Ce sont 🎜a.js🎜 et 🎜b.js🎜🎜🎜 Nous pouvons analyser la logique de mise en œuvre de l'importation et de l'exportation à travers les quatre étapes ci-dessus. 🎜🎜🎜🎜🎜Lire les fichiers. 🎜🎜🎜Introduisez le contenu du fichier qui doit être importé dans le fichier qui doit être reçu, et il ressemblera à ceci🎜rrreee🎜Mais sous cette forme, Node ne peut pas l'analyser du tout, nous devons donc procéder à la deuxième étape. 🎜🎜🎜🎜🎜Encapsulez le fichier lu dans une fonction. 🎜🎜let a = (function(exports, module, require, __dirname, __filename){ var a = 100; module.exports = function(){}; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
Copier après la connexionCopier après la connexionlet a = (function(exports, module, require, __dirname, __filename){ module.exports = "a"; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
Copier après la connexionCopier après la connexion封装成函数的原因,我们可以参考下面这个例子。
假设我们现在传入的不是字符串,而是一个函数。
// a.js var a = 100; module.exports = function(){}
Copier après la connexionCopier après la connexion这样我们在解析的时候,就会被解析成下面这种格式
let a = (function(exports, module, require, __dirname, __filename){ var a = 100; module.exports = function(){}; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
Copier après la connexionCopier après la connexion我们导出的是
module.exports
,所以在模块文件中定义的变量a,也只属于当前这个执行上下文。在解析的时候,变量a 会被放到函数中。真正的实现了 作用域分离。
-
vm.runInThisContext
解析成可执行的Js代码我们处理过的代码会以字符串的形式存在,所以我们需要通过
vm.runInThisContext
将字符串进行解析。 -
进行代码调用
在此之前,我们其实还需要对代码进行调试。
更多node相关知识,请访问:nodejs 教程!!
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

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

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)

Cet article vous donnera une compréhension approfondie de la mémoire et du garbage collector (GC) du moteur NodeJS V8. J'espère qu'il vous sera utile !

Le service Node construit sur une base non bloquante et piloté par les événements présente l'avantage d'une faible consommation de mémoire et est très adapté à la gestion de requêtes réseau massives. Dans le contexte de demandes massives, les questions liées au « contrôle de la mémoire » doivent être prises en compte. 1. Le mécanisme de récupération de place du V8 et les limitations de mémoire Js sont contrôlés par la machine de récupération de place

Le choix d'une image Docker pour Node peut sembler trivial, mais la taille et les vulnérabilités potentielles de l'image peuvent avoir un impact significatif sur votre processus CI/CD et votre sécurité. Alors, comment choisir la meilleure image Docker Node.js ?

Le module de fichiers est une encapsulation des opérations de fichiers sous-jacentes, telles que l'ajout de lecture/écriture/ouverture/fermeture/suppression de fichiers, etc. La plus grande caractéristique du module de fichiers est que toutes les méthodes fournissent deux versions de **synchrone** et ** asynchrone**, with Les méthodes avec le suffixe sync sont toutes des méthodes de synchronisation, et celles qui n'en ont pas sont toutes des méthodes hétérogènes.

Node 19 est officiellement publié. Cet article vous donnera une explication détaillée des 6 fonctionnalités majeures de Node.js 19. J'espère qu'il vous sera utile !

Comment Node.js fait-il le GC (garbage collection) ? L’article suivant vous guidera à travers cela.

La boucle d'événements est un élément fondamental de Node.js et permet une programmation asynchrone en garantissant que le thread principal n'est pas bloqué. Comprendre la boucle d'événements est crucial pour créer des applications efficaces. L'article suivant vous donnera une compréhension approfondie de la boucle d'événements dans Node. J'espère qu'il vous sera utile !

Comment empaqueter le fichier exécutable nodejs avec pkg ? L'article suivant vous expliquera comment utiliser pkg pour empaqueter un projet Node dans un fichier exécutable. J'espère qu'il vous sera utile !
