node.js最近新增了虛擬機模塊,其實也不能說是新增的,只是把一些內(nèi)部接口暴露出來罷了,從2.x就有了。我們可以從node / src / node.js看到這些代碼:
var Script = process.binding('evals').NodeScript;var runInThisContext = Script.runInThisContext; NativeModule.wrap = function(script) { return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; NativeModule.wrapper = [ '(function (exports, require, module, __filename, __dirname) { ', '/n});' ]; NativeModule.prototype.compile = function() { var source = NativeModule.getSource(this.id); source = NativeModule.wrap(source); var fn = runInThisContext(source, this.filename, true); fn(this.exports, NativeModule.require, this, this.filename); this.loaded = true; };
其中的Script對象,就與require('vm')返回的對象很相似,而實質(zhì)上,vm模塊就是對Script對象的封裝。
var Script = process.binding('evals').NodeScript;console.log(Script)/**{ [Function: NodeScript] createContext: [Function], runInContext: [Function], runInThisContext: [Function], runInNewContext: [Function] } */console.log(require('vm')){ Script: { [Function: NodeScript] createContext: [Function], runInContext: [Function], runInThisContext: [Function], runInNewContext: [Function] }, createScript: [Function], createContext: [Function], runInContext: [Function], runInThisContext: [Function], runInNewContext: [Function] }
其中,runInThisContext 相當(dāng)于一個全新的環(huán)境中執(zhí)行代碼,不會影響當(dāng)前作用域的對象。而runInNewContext與runInContext則能指定是上下文對象,區(qū)別是一個普通對象或一個context對象。換言之,runInNewContext與runInContext能局部影響當(dāng)前作用域的對象。要與當(dāng)前環(huán)境完全進(jìn)行交互的話,就需要用到危險的eval。在node.js自帶的加載體系中,顯然沒有這樣的勇氣,使用的是runInThisContext。并且在這之前做了許多工作,如把用戶的JS文件里面的內(nèi)容再包一層( NativeModule.wrap),還有其他凌散操作,加之是同步操作,實際上是一種效率很糟的加載方式。唯一的好處是,使用了同步,讓代碼編寫起來簡單多了。
在github中,已有人對這幾種動態(tài)執(zhí)行腳本的方法進(jìn)行性能比較:
var vm = require('vm'), code = 'var square = n * n;', fn = new Function('n', code), script = vm.createScript(code), sandbox; n = 5;sandbox = { n: n }; benchmark = function(title, funk) { var end, i, start; start = new Date; for (i = 0; i < 5000; i++) { funk(); } end = new Date; console.log(title + ': ' + (end - start) + 'ms');} var ctx = vm.createContext(sandbox);benchmark('vm.runInThisContext', function() { vm.runInThisContext(code); });benchmark('vm.runInNewContext', function() { vm.runInNewContext(code, sandbox); });benchmark('script.runInThisContext', function() { script.runInThisContext(); });benchmark('script.runInNewContext', function() { script.runInNewContext(sandbox); });benchmark('script.runInContext', function() { script.runInContext(ctx); });benchmark('fn', function() { fn(n); });/**vm.runInThisContext: 212msvm.runInNewContext: 2222msscript.runInThisContext: 6msscript.runInNewContext: 1876msscript.runInContext: 44msfn: 0ms */
由此可見,還是v8自帶的方法Function完勝!
以上就是本文的全部內(nèi)容,希望能給大家一個參考,也希望大家多多支持武林網(wǎng)。
新聞熱點
疑難解答