Das VM-Modul ist das Kernmodul in NodeJS. Es unterstützt die Require-Methode und den Betriebsmechanismus von NodeJS. Manchmal verwenden wir auch VM-Vorlagen, um einige spezielle Dinge zu tun. Dieser Artikel vermittelt Ihnen ein detailliertes Verständnis des VM-Moduls in Node. Ich hoffe, er wird Ihnen hilfreich sein!
Referenz VM virtuelle Maschine |. Offizielle Node-Website
http://nodejs.cn/api/vm.html
Im vorherigen Artikel haben wir ein Problem erwähnt.
Wie kann ein String zur Ausführung in JS umgewandelt werden?
Wir haben zwei Methoden im Detail vorgestellt, nämlich Bewertungsfunktion und Neue Funktion.
Wir müssen hier noch einmal betonen, dass vom Function
-Konstruktor erstellte Funktionen keine Abschlüsse der aktuellen Umgebung erzeugen. Sie werden immer in der globalen Umgebung erstellt, sodass auf sie nur zur Laufzeit zugegriffen werden kann Variablen und ihre eigenen lokalen Variablen können nicht auf Variablen in dem Bereich zugreifen, in dem sie vom Function
-Konstruktor erstellt wurden. Dies steht im Einklang mit der Verwendung von 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的特点就是不受环境的影响,也可以说他就是一个 沙箱环境 (沙箱模式给模块提供一个环境运行而不影响其它模块和它们私有的沙箱)。
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
Der Code, der die Erstellungsfunktion ausführt, ist unterschiedlich.
// 文件a通过module.exports导出一个变量,在文件b中使用require进行接收。 // a.js module.exports = "a" // b.js let a = require('./a'); console.log(a); // a
Funktion
kann globale Variablen abrufen, daher kann es immer noch zu einer Variablenverschmutzung kommen. Funktion
ist das Implementierungsprinzip der . Ich werde in Zukunft einen Artikel veröffentlichen, um es separat zu erklären.
vm
. Im obigen Text habe ich ein Konzept hervorgehoben, nämlich Verschmutzung von Variablen. Das Merkmal von VM ist, dass es nicht von der Umgebung beeinflusst wird. Man kann auch sagen, dass es sich um eine Sandbox-Umgebung handelt (Der Sandbox-Modus bietet eine Umgebung, in der Module ausgeführt werden können, ohne andere Module zu beeinträchtigen ihre privaten Sandkästen).
let a = module.exports = "a";
Wir möchten hier betonen, dass globale Variablen in
Node.jsAngenommen, wir haben eine Datei 1.js im selben Verzeichnis, die global.a = 100;
definiert. Nachdem wir nun diese Datei eingeführt haben
let a = (function(exports, module, require, __dirname, __filename){ module.exports = "a"; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
, können wir feststellen, dass wir die Variable a nicht in der aktuellen Datei definieren, sondern nur die beiden Moduldateien miteinander verknüpfen. Das habe ich oben erwähnt: Globale Variablen in Node werden von mehreren Modulen gemeinsam genutzt.
Der Grund dafür ist, dass es in der Umgebung von
Node// a.js var a = 100; module.exports = function(){}
vm.runInThisContext
kann also auf globale Variablen auf global
zugreifen, aber nicht auf benutzerdefinierte Variablen. Allerdings kann vm.runInNewContext
nicht auf global
zugreifen, noch kann es auf benutzerdefinierte Variablen zugreifen. Es existiert in einem völlig neuen Ausführungskontext. Und unser require
wird durch vm.runInThisContext
implementiert.
require
kann in die folgenden vier Schritte unterteilt werden. 🎜🎜🎜🎜Lesen Sie die Dateien, die importiert werden müssen. 🎜🎜🎜🎜Nachdem Sie die Datei gelesen haben, kapseln Sie den Code in eine Funktion. 🎜🎜🎜🎜Konvertieren Sie es über vm.runInThisContext
in JS-Syntax. 🎜🎜🎜🎜Codeanruf. 🎜🎜🎜🎜Angenommen, wir haben jetzt die folgenden zwei Dateien. Sie sind 🎜a.js🎜 und 🎜b.js🎜🎜let a = (function(exports, module, require, __dirname, __filename){ var a = 100; module.exports = function(){}; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
let a = (function(exports, module, require, __dirname, __filename){ module.exports = "a"; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
封装成函数的原因,我们可以参考下面这个例子。
假设我们现在传入的不是字符串,而是一个函数。
// a.js var a = 100; module.exports = function(){}
这样我们在解析的时候,就会被解析成下面这种格式
let a = (function(exports, module, require, __dirname, __filename){ var a = 100; module.exports = function(){}; return module.exports })(...args) // exports, module, require, __dirname, __filename 将五个参数传入
我们导出的是 module.exports
,所以在模块文件中定义的变量a,也只属于当前这个执行上下文。
在解析的时候,变量a 会被放到函数中。真正的实现了 作用域分离。
vm.runInThisContext
解析成可执行的Js代码
我们处理过的代码会以字符串的形式存在,所以我们需要通过vm.runInThisContext
将字符串进行解析。
进行代码调用
在此之前,我们其实还需要对代码进行调试。
更多node相关知识,请访问:nodejs 教程!!
Das obige ist der detaillierte Inhalt vonEin tiefer Einblick in das VM-Modul in Node.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!