nodejs模块源码require问题
发布于 2 年前 作者 chenqichenqi 3059 次浏览 来自 问答

这是nodejs源码module.js的代码 https://github.com/nodejs/node/blob/master/lib/module.js const NativeModule = require(‘native_module’); const util = require(‘util’); const internalModule = require(‘internal/module’); const vm = require(‘vm’); const assert = require(‘assert’).ok; const fs = require(‘fs’); const internalFS = require(‘internal/fs’);

这是require的源码 Module.prototype.require = function(path) { assert(path, ‘missing path’); assert(typeof path === ‘string’, ‘path must be a string’); return Module._load(path, this, / isMain / false); };

module.js是实现require函数的,为什么第一行就调用了require,require函数不是还没实现吗?,那么第一行的require是哪里的? https://github.com/nodejs/node/blob/master/lib/internal/module.js internal目录下的module.js又是做什么用的呢?

一般每个模块默认会加上(function (exports, require, module, __filename, __dirname) { // 模块源码 }); 这里的require又是哪里的? 好混乱啊,求各位大神指教,谢谢!

6 回复

看看require的源码就可以看到了: Module.prototype.require -> Module._load ->

	var filename = Module._resolveFilename(request, parent, isMain);
	if (NativeModule.nonInternalExists(filename)) {
    	debug('load native module %s', request);
    	return NativeModule.require(filename);
	}

所以 module.js 第一行的 require 调用的是 NativeModule.require,专门载入核心模块的。

@hyj1991 const NativeModule = require(‘native_module’); 这个require后面是Module.prototype.require -> Module._load ->会判断然后调用 NativeModule.require(filename); ,但NativeModule这个是require来的啊,这不是自相矛盾吗?

至于你提到的 internal/module.js,也很简单,这里面提供了三个函数:

  • makeRequireFunction:生成一个 require 函数,这个 require 函数就是开发者编写的js文件直接使用的 require 关键字对应的函数

  • stripBOM:因为 require 操作本质上会读取js文件内容,这个函数用来对读取出来的js文件内容进行BOM头剥离,主要是处理编码问题的

  • addBuiltinLibsToObject:给node真正的入口js文件 bootstrap_node.js 构造一些内建模块到 global 对象上用的,比如:assert, buffer

@chenqichenqi 建议你再仔细看看源代码,所有代码第一次执行前 boot_strap_node.js 已经被执行了,你编写的入口js文件已经被这个文件包裹后执行,所以此时 require 已经定义了。所以在 boot_strap_node.js 中的所有 require 操作都是使用 NativeModule.require,而在这里的 NativeModule 定义就在 boot_strap_node.js 中,所以不会自相矛盾

@chenqichenqi 在最开始,node中真正的第一次 require('module') 操作发生在 boot_strap_node.js 中,此时使用的是 NativeModule.require('module'):

const Module = NativeModule.require('module');
//...省略
Module.runMain()

而这里的 NativeModule 就定义在 boot_strap_node.js文件中,并且NativeModule.require('module') 调用了 NativeModule.prototype.compilemodule 核心类进行了编译,你可以看看这里的处理逻辑,此时构建的匿名函数传入的 require 还是 NativeModule.require,所以并没有矛盾。

当然 NativeModule.require 获取源代码的方式和 module.js 中的 require 方法不一样,是通过 process.binding('natives')['module'] 的方式从C源码部分获取的

@hyj1991 恩,谢谢,我再看看源码

回到顶部