首页前端开发JavaScript深入了解Node.js中的VM模块

深入了解Node.js中的VM模块

时间2024-01-30 20:56:02发布访客分类JavaScript浏览471
导读:收集整理的这篇文章主要介绍了深入了解Node.js中的VM模块,觉得挺不错的,现在分享给大家,也给大家做个参考。VM模块是NodeJS里面的核心模块,支撑了require方法和NodeJS的运行机制,我们有些时候可能也要用到VM模板来做一些...
收集整理的这篇文章主要介绍了深入了解Node.js中的VM模块,觉得挺不错的,现在分享给大家,也给大家做个参考。VM模块是NodeJS里面的核心模块,支撑了require方法和NodeJS的运行机制,我们有些时候可能也要用到VM模板来做一些特殊的事情。本篇文章就来带大家详细了解下Node中的VM模块,希望对大家有所帮助!

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

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

在上一篇文章中,我们提到了一个问题。

字符串如何能变成 JS 执行呢?

我们详细介绍了两种方法,分别是 eval函数 和 new Function 。

在这里我们需要再强调一下, 由 Function 构造器创建的函数不会创建当前环境的闭包,它们总是被创建于全局环境,因此在运行时它们只能访问全局变量和自己的局部变量,不能访问它们被 Function 构造器创建时所在的作用域的变量。这一点与使用 eval 执行创建函数的代码不同。

global.a = 100;
     // 挂在到全局对象global上VAR b = 200;
     // this !== globalnew Function("console.LOG(a)")() // 100new 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 将他转变成 JS 语法。

  • 代码调用。

假设我们现在有以下两个文件。分别是 a.jsb.js

// 文件a通过module.exports导出一个变量,在文件b中使用require进行接收。// a.jsmodule.exports = "a"// b.jslet 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.jsvar 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模块的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: jquery怎样给div增加内容下一篇:jquery怎么改变href的值猜你在找的JavaScript相关文章 html font标签如何设置字体大小?html font标签属性用法介绍2022-05-16vue3+TypeScript+vue-router的使用方法2022-04-16vue3获取当前路由地址2022-04-16如何利用React实现图片识别App2022-04-16JavaScript展开运算符和剩余运算符的区别详解2022-04-16微信小程序中使用vant框架的具体步骤2022-04-16Vue elementUI表单嵌套表格并对每行进行校验详解2022-04-16如何利用Typescript封装本地存储2022-04-16微信小程序中wxs文件的一些妙用分享2022-04-16JavaScript的Set数据结构详解2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

若转载请注明出处: 深入了解Node.js中的VM模块
本文地址: https://pptw.com/jishu/593028.html
jquery怎么替换类样式 IIS如何实现部署asp.net mvc网站的方法

游客 回复需填写必要信息