使用exports导出模块
module.exports = {
name: 'Tom'
};引用的名称可以不带路径,若不带路径表示引入的是node提供的模块或是npm安装的第三方模块(node_modules)
模块定义
module对象:在每一个模块中,module对象代表该模块自身。
export属性:module对象的一个属性,它向外提供接口。
模块标识
模块标识指的是传递给require方法的参数,必须是符合小驼峰命名的字符串,或者以 .、..、开头的相对路径,或者绝对路径。
node中模块解析流程
首先接收参数,把传入的模块名称解析成绝对路径
若没有后缀名称,依次拼接.js .json .node尝试加载,仍到不到模块则报错
取得正确的路径后判断缓存中是否存在此模块,若有则取出
若缓存中不存在则加载此文件,在外包裹一层闭包并执行它
以上为大致流程,下面尝试着写一下模块。
代码的基本结构:
/**
* Module类,用于处理模块加载
*/
function Module() {}//模块的缓存
Module._cacheModule = {};
//不同扩展名的加载策略
Module._extensions = {};
//根据moduleId解析绝对路径,
Module._resolveFileName = function(moduleId) {};
//入口函数
function req(moduleId) {}
附上全部代码:
const path = require('path');
const fs = require('fs');
const vm = require('vm');/**
* Module类,用于处理模块加载
*/
function Module(file) {
this.id = file; //当前模块的id,它使用完整的绝对路径标识,因此是唯一的
this.exports = {}; //导出
this.loaded = false; //模块是否已加载完毕
}
//模块的缓存
Module._cacheModule = {};
Module._wrapper = ['(function(exports,require,module,__dirname,__filename){', '});'];
//不同扩展名的加载策略
Module._extensions = {
'.js': function(currentModule) {
let js = fs.readFileSync(currentModule.id, 'utf8'); //读取出js文件内容
let fn = Module._wrapper[0] + js + Module._wrapper[1];
vm.runInThisContext(fn).call(
currentModule.exports,
currentModule.exports,
req,
currentModule,
path.dirname(currentModule.id),
currentModule.id);
return currentModule.exports;
},
'.json': function(currentModule) {
let json = fs.readFileSync(currentModule.id, 'utf8');
return JSON.parse(json); //转换为JSON对象返回
},
'.node': ''
};
//加载模块(实例方法)
Module.prototype.load = function(file) {
let extname = path.extname(file); //获取后缀名
return Module._extensions[extname](this);









