WWW.lllT.neTVM控制模块是NodeJS里边的关键控制模块,支撑点了require方式和NodeJS的运行机制,大家很多情况下很有可能也需要使用VM模版来做一些特别的事儿。这篇文章内容就来带大伙儿具体认识下Node中的VM控制模块,期待对各位有些协助!

论文参考文献 vm vm虚拟机 | Node 官方网站

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

在上一篇文章中,大家提起了一个问题。

字符串数组怎样能变为 JS 实行呢?

大家介绍了二种方式,分别是 eval涵数 和 new Function 。

在这儿大家必须再注重一下, 由 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,只不过是把2个控制模块文件关联在了一起。这便是我上边提及的,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 将他转化成 JS 英语的语法。

  • 编码读取。

假定大家现在有下列2个文档。分别是 a.jsb.js

// 文档a根据module.exports导出来一个自变量,在文档b中应用require开展接受。
// a.js
module.exports = "a"
// b.js
let a = require('./a');
console.log(a); // a

我们可以根据之前的四个流程,剖析一下导入导出的完成逻辑性是哪样的。

  • 读取文件。

    将必须引进的文档具体内容引进到必须接受的文档里,便会成为这一模样

    let a = module.exports = "a";

    可是这类方式,Node压根分析不上,因此大家就必须开展第二步。

  • 将获取的文档封装形式成涵数。

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

以上便是深入了解Node.js中的VM控制模块的详尽具体内容,大量请关心自学java网其他相关文章!

WWW.lllT.neT

声明:有的资源来自网络转载,版权归原作者所有,如有侵犯到您的权益请联系邮箱:our333@126.com我们将配合处理!

原文地址:深入了解Node.js中的VM控制模块发布于2021-12-10 16:09:01