代码之家  ›  专栏  ›  技术社区  ›  Harish_N

require in node是否使用eval在另一个文件中运行代码

  •  3
  • Harish_N  · 技术社区  · 7 年前

    我只是想理解node中的模块。我了解了一些事情,比如node围绕每个文件中的代码创建一个模块包装器函数。

    在a.js中,当我第一次需要b.js时,b.js中的模块包装器函数将如何执行。

    eval 然后将此函数调用的结果保存在缓存中。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Estus Flask    7 年前

    或多或少。

    Node.js loads 脚本文件内容和 wraps 具有 module wrapper :

    Module.wrap = function(script) {
      return Module.wrapper[0] + script + Module.wrapper[1];
    };
    
    Module.wrapper = [
      '(function (exports, require, module, __filename, __dirname) { ',
      '\n});'
    ];
    

    则模块功能为 evaluated vm.runInThisContext

      var wrapper = Module.wrap(content);
    
      var compiledWrapper = vm.runInThisContext(wrapper, {
        filename: filename,
        lineOffset: 0,
        displayErrors: true
      });
    

    vm 模块提供 V8 execution context ,和 vm.runInThisContext 以类似于间接的方式计算代码 eval

    vm.runInThisContext()编译代码,在当前全局的上下文中运行并返回结果。运行的代码无权访问本地范围,但可以访问当前全局对象。

    <

    因为vm.runInThisContext()没有访问本地作用域的权限,localVar未更改。相反,eval()确实可以访问本地作用域,因此localVar的值被更改。以这种方式vm.runInThisContext()非常类似于间接eval()调用,例如(0,eval)('code')。

        2
  •  1
  •   Sourabh Somani    7 年前

    1. 首先,它检查缓存模块中是否存在该模块。检查由 模块。\u缓存
    2. 保存到缓存
    3. 呼叫模块负载()使用给定的文件名。 这将呼叫模块.编译()读取文件内容后。
    4. 如果解析文件时出错(因为任何编译器进行编译时都有词法分析和解析步骤),则从缓存中删除模块

    我们知道node是开源的,我直接给出了github的路径加载器.js的节点.js

    Path of loader.js

    这是模块的代码。加载函数是由Node.js 团队

    // Check the cache for the requested file.
    // 1. If a module already exists in the cache: return its exports object.
    // 2. If the module is native: call `NativeModule.require()` with the
    //    filename and return the result.
    // 3. Otherwise, create a new module for the file and save it to the cache.
    //    Then have it load  the file contents before returning its exports
    //    object.
    Module._load = function(request, parent, isMain) {
      if (parent) {
        debug('Module._load REQUEST %s parent: %s', request, parent.id);
      }
    
      var filename = Module._resolveFilename(request, parent, isMain);
    
      var cachedModule = Module._cache[filename];
      if (cachedModule) {
        updateChildren(parent, cachedModule, true);
        return cachedModule.exports;
      }
    
      if (NativeModule.nonInternalExists(filename)) {
        debug('load native module %s', request);
        return NativeModule.require(filename);
      }
    
      // Don't call updateChildren(), Module constructor already does.
      var module = new Module(filename, parent);
    
      if (isMain) {
        process.mainModule = module;
        module.id = '.';
      }
    
      Module._cache[filename] = module;
    
      tryModuleLoad(module, filename);
    
      return module.exports;
    };
    

    How require() Actually Works