Node.js中的VM模塊怎么使用

本篇內(nèi)容主要講解“Node.js中的VM模塊怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Node.js中的VM模塊怎么使用”吧!

網(wǎng)站的建設(shè)成都創(chuàng)新互聯(lián)公司專注網(wǎng)站定制,經(jīng)驗(yàn)豐富,不做模板,主營網(wǎng)站定制開發(fā).小程序定制開發(fā),H5頁面制作!給你煥然一新的設(shè)計(jì)體驗(yàn)!已為石涼亭等企業(yè)提供專業(yè)服務(wù)。

Node.js中的VM模塊怎么使用

參考文獻(xiàn) vm 虛擬機(jī) | Node 官網(wǎng)

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

在上一篇文章中,我們提到了一個(gè)問題。

字符串如何能變成 JS 執(zhí)行呢?

我們詳細(xì)介紹了兩種方法,分別是 eval函數(shù) 和 new Function 。

在這里我們需要再強(qiáng)調(diào)一下, 由 Function 構(gòu)造器創(chuàng)建的函數(shù)不會創(chuàng)建當(dāng)前環(huán)境的閉包,它們總是被創(chuàng)建于全局環(huán)境,因此在運(yùn)行時(shí)它們只能訪問全局變量和自己的局部變量,不能訪問它們被 Function 構(gòu)造器創(chuàng)建時(shí)所在的作用域的變量。這一點(diǎn)與使用 eval 執(zhí)行創(chuàng)建函數(shù)的代碼不同。

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 可以獲取全局變量,所以他還是可能會有變量污染的情況出現(xiàn)。Function模塊引擎的實(shí)現(xiàn)原理 ,后續(xù)我會出一篇文章進(jìn)行單獨(dú)講解。

還有一種解決方案,我們在上一次文章中沒有進(jìn)行詳細(xì)的展開,那就是 vm模塊。

vm模塊

在上述文字中,我一直在強(qiáng)調(diào)一個(gè)概念,那就是 變量的污染

VM的特點(diǎn)就是不受環(huán)境的影響,也可以說他就是一個(gè) 沙箱環(huán)境(沙箱模式給模塊提供一個(gè)環(huán)境運(yùn)行而不影響其它模塊和它們私有的沙箱)。

const vm = require('vm')
global.a = 100;
// 運(yùn)行在當(dāng)前環(huán)境中[當(dāng)前作用域]
vm.runInThisContext('console.log(a)'); // 100
// 運(yùn)行在新的環(huán)境中[其他作用域]
vm.runInNewContext('console.log(a)'); // a is not defined

在這里我們要強(qiáng)調(diào)一下,因?yàn)?在Node.js中全局變量是在多個(gè)模塊下共享的,所以盡量不要在global中定義屬性。Demo中的定義是為了方便理解。

假設(shè)我們在同級目錄下有一個(gè)文件 1.js ,里面定義了 global.a = 100;。 現(xiàn)在我們引入這個(gè)文件

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

我們可以發(fā)現(xiàn),在當(dāng)前文件中我們并沒有定義變量a,僅僅只是把兩個(gè)模塊文件關(guān)聯(lián)在了一起。這就是我上面提到的,Node中全局變量是在多個(gè)模塊下共享的。

他的原理是因?yàn)樵?Node 的環(huán)境中,全局中有一個(gè)執(zhí)行上下文。

// 模擬一下Node的全局環(huán)境
// vm.runInThisContext在當(dāng)前全局環(huán)境執(zhí)行,但不會產(chǎn)生新函數(shù)
- function(exports, module, require, __dirname, __filename){ // ... }
- vm.runInThisContext ...
// vm.runInNewContext在全局環(huán)境之外執(zhí)行
vm.runInNewContext ...

所以,vm.runInThisContext 可以訪問到 global上的全局變量,但是訪問不到自定義的變量。而 vm.runInNewContext 訪問不到 global,也訪問不到自定義變量,他存在于一個(gè)全新的執(zhí)行上下文。

而我們require 就是通過 vm.runInThisContext 實(shí)現(xiàn)的。

實(shí)現(xiàn)require 主要可以分為以下四步。

  • 讀取需要引入的文件。

  • 讀取到文件后,將代碼封裝成一個(gè)函數(shù)。

  • 通過 vm.runInThisContext 將他轉(zhuǎn)變成 JS 語法。

  • 代碼調(diào)用。

假設(shè)我們現(xiàn)在有以下兩個(gè)文件。分別是 a.jsb.js

// 文件a通過module.exports導(dǎo)出一個(gè)變量,在文件b中使用require進(jìn)行接收。
// a.js
module.exports = "a"
// b.js
let a = require('./a');
console.log(a); // a

我們可以通過上面的四個(gè)步驟,分析一下導(dǎo)入導(dǎo)出的實(shí)現(xiàn)邏輯是什么樣的。

  • 讀取文件。

    將需要引入的文件內(nèi)容引入到需要接收的文件里,就會變成這個(gè)樣子

    let a = module.exports = "a";

    但是這種形式,Node根本解析不了,所以我們就需要進(jìn)行第二步。

  • 將讀取的文件封裝成函數(shù)。

    let a = (function(exports, module, require, __dirname, __filename){
      module.exports = "a";
      return module.exports
    })(...args) // exports, module, require, __dirname, __filename 將五個(gè)參數(shù)傳入

    封裝成函數(shù)的原因,我們可以參考下面這個(gè)例子。

    假設(shè)我們現(xiàn)在傳入的不是字符串,而是一個(gè)函數(shù)。

    // a.js
    var a = 100;
    module.exports = function(){}

    這樣我們在解析的時(shí)候,就會被解析成下面這種格式

    let a = (function(exports, module, require, __dirname, __filename){
      var a = 100;
      module.exports = function(){};
      return module.exports
    })(...args) // exports, module, require, __dirname, __filename 將五個(gè)參數(shù)傳入

    我們導(dǎo)出的是 module.exports,所以在模塊文件中定義的變量a,也只屬于當(dāng)前這個(gè)執(zhí)行上下文。

    在解析的時(shí)候,變量a 會被放到函數(shù)中。真正的實(shí)現(xiàn)了 作用域分離

  • vm.runInThisContext 解析成可執(zhí)行的Js代碼

    我們處理過的代碼會以字符串的形式存在,所以我們需要通過vm.runInThisContext將字符串進(jìn)行解析。

  • 進(jìn)行代碼調(diào)用

    在此之前,我們其實(shí)還需要對代碼進(jìn)行調(diào)試。

到此,相信大家對“Node.js中的VM模塊怎么使用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

文章名稱:Node.js中的VM模塊怎么使用
分享地址:http://muchs.cn/article44/ihisee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、微信公眾號、虛擬主機(jī)標(biāo)簽優(yōu)化、外貿(mào)建站、手機(jī)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)