Node.js の VM モジュールの詳細

青灯夜游
青灯夜游転載
2021-11-22 19:36:183498ブラウズ

VM モジュールは NodeJS のコア モジュールであり、require メソッドと NodeJS の操作メカニズムをサポートします。場合によっては、特別なことを行うために VM テンプレートを使用することもあります。この記事では、Node の VM モジュールについて詳しく説明します。お役に立てば幸いです。

Node.js の VM モジュールの詳細

#リファレンス vm 仮想マシン | Node 公式 Web サイト

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

前の記事で、問題について触れました。

文字列を実行用の JS に変換するにはどうすればよいでしょうか?

eval functionnew Function という 2 つのメソッドを詳しく紹介しました。

ここで、

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 はグローバル変数を取得できるため、変数汚染が依然として存在する可能性があります。 関数モジュールエンジンの実装原理であり、今後別途記事で解説する予定です。

前回の記事では詳しく説明しませんでしたが、

vmmodule という別の解決策があります。

vm module

上記のテキストでは、

変数の汚染という概念を強調してきました。

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.a = 100; を定義するファイル 1.js があるとします。ここで、このファイルを紹介します

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.runInThisContextglobal のグローバル変数にアクセスできますが、カスタム変数にはアクセスできません。ただし、vm.runInNewContextglobal にアクセスできず、カスタム変数にもアクセスできず、まったく新しい実行コンテキストに存在します。

そして、

requirevm.runInThisContext を通じて実現されます。

実装

requireは以下の4つのステップに分けられます。

    #インポートする必要があるファイルをお読みください。
  • ファイルを読み込んだ後、コードを関数にカプセル化します。
  • vm.runInThisContext

    を通じて JS 構文に変換します。

  • コード呼び出し。
  • 次の 2 つのファイルがあるとします。
a.js

b.js

// 文件a通过module.exports导出一个变量,在文件b中使用require进行接收。
// a.js
module.exports = "a"
// b.js
let a = require('./a');
console.log(a); // a
です。 上記の 4 つの手順でインポートとエクスポートの実装ロジックを分析できます。

    #ファイルを読んでください。
  • インポートする必要のあるファイルの内容を受信する必要のあるファイルに挿入すると、次のようになります。

    let a = module.exports = "a";

    ただし、この形式では Node は解析できませんまったく問題がないので、ステップ 2 に進む必要があります。

  • 読み取ったファイルを関数にカプセル化します。
  • 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 モジュールの詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。