node.js has recently added a virtual machine module. In fact, it cannot be said that it is a new one. It just exposes some internal interfaces, which have been available from 2.x. We can see these codes from 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; };The Script object in it is very similar to the object returned by require('vm'), but in essence, the vm module is the encapsulation of the Script object.
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] }Among them, runInThisContext is equivalent to executing code in a brand new environment and will not affect the object in the current scope. runInNewContext and runInContext can be specified as context objects, the difference is a normal object or a context object. In other words, runInNewContext and runInContext can locally affect objects in the current scope. To fully interact with the current environment, dangerous evals are required. In the loading system that comes with node.js, it is obviously not so courageous, and it uses runInThisContext. And I did a lot of work before this, such as wrapping the contents of the user's JS file in a layer (NativeModule.wrap), and other scatter operations, plus synchronous operations, which is actually a very efficient loading method. The only benefit is that the synchronization is used, making the code much easier to write.
In github, some people have compared the performance of these methods of dynamically executing scripts:
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', function() { script.runInNewContext(); });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 */From this we can see that the V8 method is the complete victory!
The above is the entire content of this article. I hope you can give you a reference and I hope you can support Wulin.com more.