爲了減小變量污染以及代碼維護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