为了减少变量污染以及代码维护node采用了CommonJS规范。今天模拟一下Module。
- 首先创建被引入文件 a.js
module.exports = 'hello';
- 创建Module文件
//定义Module类
class Module{
constructor(filename){
this.filename = filename;
this.exports = {};
}
}
//定义require方法
function myRequire(){
}
let resut = myRequire('./a');
- 获取文件路径
function myRequire(filename){
//获取文件绝对路径
filename = Module.getPath(filename);
}
class Module{
...
//Module下定义静态方法
static getPath(filename){
filename = path.join(__dirname,filename);
let ext = path.extname(filename);
let pathName = '';
let error = filename + " is not exist";
//判断文件是否存在拓展名
if(ext){
try{
fs.accessSync(filename);
return filename;
}catch(e){
throw error;
}
}
for(var i=0; i<Module.extentions.length; i++){
//给文件加上拓展名,查找文件是否存在
pathName = filename + Module.extentions[i];
try{
fs.accessSync(pathName);
return pathName;
}catch(e){}
}
throw error;
}
}
//定义拓展名
Module.extentions = ['.js','.json','.node'];
- 读取文件
class Module{
...
load(){
let ext = path.extname(this.filename).slice(1);
//根据文件类型读取文件
Module.extentions[ext](this);
}
static wrap(script){
return Module.warper[0] + script + Module.warper[1];
}
}
Module.extentions["js"] = function(module){
let script = fs.readFileSync(module.filename,'utf8');
let fnStr = Module.wrap(script);
//(function(exports,require,module,__dirname,__filename){module.exports = 'hello'})
let dirname = path.resolve(module.filename,'../');
vm.runInThisContext(fnStr).call(module.exports,module.exports,myRequire,module,dirname,module.filename);
//文件内部会获得传过来的module对象
//模块内部将要导出的文件挂载到module.exports上
//module.exports = 'hello'
}
Module.extentions["json"] = function(module){
let script = fs.readFileSync(module.filename,'utf8');
module.exports = JSON.parse(script);
}
//用于拼接嵌套js文件
Module.warper = ["(function(exports,require,module,__dirname,__filename){", "\n})"];
function myRequire(filename){
...
let module = new Module(filename);
module.load();
}
- 暂存已读取文件
function myRequire(filename){
let fileCache = Module.caches[filename];
//有缓存读取缓存
if(fileCache){
return fileCache.exports;
}
//加载文件
let module = new Module(filename);
module.load();
//缓存文件
Module.caches[filename] = module;
}
- 完整代码
a.js
module.exports = 'hello'
module.js
let path = require('path');
let fs = require('fs');
let vm = require('vm');
class Module{
constructor(filename){
this.filename = filename;
this.exports = {};
}
load(){
let ext = path.extname(this.filename).slice(1);
Module.extentions[ext](this);
}
static wrap(script){
return Module.warper[0] + script + Module.warper[1];
}
static getPath(filename){
filename = path.join(__dirname,filename);
let ext = path.extname(filename);
let pathName = '';
let error = filename + " is not exist";
if(ext){
try{
fs.accessSync(filename);
return filename;
}catch(e){
throw error;
}
}
for(var i=0; i<Module.extentions.length; i++){
pathName = filename + Module.extentions[i];
try{
fs.accessSync(pathName);
return pathName;
}catch(e){}
}
throw error;
// path.resolve(__dirname, filename);
}
}
Module.extentions = ['.js','.json','.node'];
Module.caches = {};
Module.warper = ["(function(exports,require,module,__dirname,__filename){", "\n})"];
Module.extentions["js"] = function(module){
let script = fs.readFileSync(module.filename,'utf8');
let fnStr = Module.wrap(script);
let dirname = path.resolve(module.filename,'../');
vm.runInThisContext(fnStr).call(module.exports,module.exports,myRequire,module,dirname,module.filename);
}
Module.extentions["json"] = function(module){
let script = fs.readFileSync(module.filename,'utf8');
module.exports = script;
}
function myRequire(filename){
//查找文件绝对路径
filename = Module.getPath(filename);
let fileCache = Module.caches[filename];
if(fileCache){
return fileCache.exports;
}
//加载文件
let module = new Module(filename);
module.load();
Module.caches[filename] = module;
return module.exports;
}
let school = myRequire('./a.js');
欢迎大家指出问题提出见解!