Fork me on GitHub

Nodejs 之 exports, require, module, __filename, __dirname

开头

Nodejs代码中常见的引入模块函数“require”。其实很少人了解为什么能使用“require”,以及Nodejs基本的运行机制。

是否还记得“arguments”,arguments可以直接拿到调用函数传入的参数。

(function() {
  console.log(arguments)} // [1, 2, 3]
)(1, 2, 3)

其实Nodejs可以直接打印 arguments。用Node运行文件:

// index.js
// node index.js 运行
console.log(arguments)
// 输出
//{ '0': {},
//  '1':{ [Function: require]
//  '2':
//   Module {
//     id: '.',
//     exports: {},
//     parent: null,
//     filename: 'D:\\Personal\\Desktop\\a
//     loaded: false,
//     children: [],
//     paths:
//      [ 'D:\\Personal\\Desktop\\abc\\nod
//        'D:\\Personal\\Desktop\\node_mod
//        'D:\\Personal\\node_modules',
//        'D:\\node_modules' ] },
//  '3': 'D:\\Personal\\Desktop\\abc\\inde
//  '4': 'D:\\Personal\\Desktop\\abc' }

可以看到arguments内有五个参数。这五个参数分别是 exports, require, module, __filename, __dirname

源码解析

在Nodejs源码 loader.js文件中,可以看到这几行js代码

Module.wrap = function(script) {
  return Module.wrapper[0] + script + Module.wrapper[1];
};

Module.wrapper = [
  '(function (exports, require, module, __filename, __dirname) { ',
  '\n});'
];

// ....
Module.prototype._compile = function(content, filename) {
 content = internalModule.stripShebang(content);
  // create wrapper function
 var wrapper = Module.wrap(content);
// ....

大致逻辑是:

在执行文件内容的头部添加 '(function (exports, require, module, __filename, __dirname) { '

在执行文件内容尾部添加 '\n});'

之后的解析就是把字符串转为代码(函数)供来调用。

备注

exports
require
module
__filename
__dirname