为了减小变量污染以及代码维护node采用了CommonJS规范。今天模拟一下Module。node
module.exports = 'hello';
复制代码
//定义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.jsjson
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');
复制代码
欢迎你们指出问题提出看法!bash