Home  >  Article  >  Web Front-end  >  A deep dive into the VM module in Node.js

A deep dive into the VM module in Node.js

青灯夜游
青灯夜游forward
2021-11-22 19:36:183458browse

The VM module is the core module in NodeJS, which supports the require method and the operating mechanism of NodeJS. Sometimes we may also use VM templates to do some special things. This article will give you a detailed understanding of the VM module in Node. I hope it will be helpful to you!

A deep dive into the VM module in Node.js

Reference vm virtual machine | Node official website

http://nodejs.cn/api/vm.html

In the previous article, we mentioned a problem.

How can a string be turned into JS for execution?

We introduced two methods in detail, namely eval function and new Function.

Here we need to emphasize again that functions created by the Function constructor do not create closures of the current environment. They are always created in the global environment, so they are created at runtime. You can only access global variables and your own local variables, not variables in the scope in which they were created by the Function constructor. This is different from using eval to execute code that creates a function.

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 can obtain global variables, so it may still have variable pollution. Function is the implementation principle of module engine. I will publish an article to explain it separately in the future.

There is another solution, which we did not expand on in detail in the last article, that is vmmodule.

vm module

In the above text, I have been emphasizing a concept, which is the pollution of variables.

The characteristic of VM is that it is not affected by the environment. It can also be said that it is a sandbox environment (Sandbox mode provides an environment for modules to run without affecting other modules and Their private sandbox).

const vm = require('vm')
global.a = 100;
// 运行在当前环境中[当前作用域]
vm.runInThisContext('console.log(a)'); // 100
// 运行在新的环境中[其他作用域]
vm.runInNewContext('console.log(a)'); // a is not defined

We want to emphasize here that because global variables in Node.js are shared under multiple modules, try not to define properties in global. The definitions in the Demo are for ease of understanding.

Suppose we have a file 1.js in the same directory, which defines global.a = 100;. Now we introduce this file

requrie(./1);
console.log(a); // 100

We can find that we do not define variable a in the current file, we just associate the two module files together. This is what I mentioned above, global variables in Node are shared under multiple modules.

The reason is that in the Node environment, there is an execution context globally.

// 模拟一下Node的全局环境
// vm.runInThisContext在当前全局环境执行,但不会产生新函数
- function(exports, module, require, __dirname, __filename){ // ... }
- vm.runInThisContext ...
// vm.runInNewContext在全局环境之外执行
vm.runInNewContext ...

So, vm.runInThisContext can access global variables on global, but cannot access custom variables. However, vm.runInNewContext cannot access global, nor can it access custom variables. It exists in a brand new execution context.

And our require is achieved through vm.runInThisContext.

Implementationrequire can be divided into the following four steps.

  • Read the files that need to be imported.

  • After reading the file, encapsulate the code into a function.

  • Convert it into JS syntax through vm.runInThisContext.

  • Code call.

Suppose we now have the following two files. They are a.js and b.js

// 文件a通过module.exports导出一个变量,在文件b中使用require进行接收。
// a.js
module.exports = "a"
// b.js
let a = require('./a');
console.log(a); // a

We can analyze the implementation logic of import and export through the above four steps.

  • Read the file.

    Introduce the content of the file that needs to be imported into the file that needs to be received, and it will look like this

    let a = module.exports = "a";

    But in this form, Node cannot parse it at all, so we need Go to step two.

  • Encapsulate the read file into a function.

    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 教程!!

The above is the detailed content of A deep dive into the VM module in Node.js. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete