node乞丐版require方法

作者 : 开心源码 本文共2294个字,预计阅读时间需要6分钟 发布时间: 2022-05-13 共241人阅读

在node环境中,每一个文件都是一个模块,处理了命名冲突的问题,node会默认给js加上一个函数,比方一个js文件打印this:

console.log(this);//{}

并不是像浏览器一样,this是window(node没有window,只有global),而是一个空对象,再打印arguments:

  '0': {},  '1': { [Function: require]  '2':Module   '3': 'E:\\mydata\\project\\bootstrap\\html\\coding\\nodenodule\\a.js',  '4': 'E:\\mydata\\project\\bootstrap\\html\\coding\\nodenodule' 

内容有点多,可以自行打印看看,但是可以看到,是五个参数,通过一个大佬的对node的调试和过程分析,确定require方法引入的时候相当于一个自执行函数:

(function (exports, require, module, __filename, __dirname) {})

且我们可以实现一个简易的require方法:

1、_resolveFilename解决路径,判断存在和转换成绝对路径

2、创立module实例new Module

3、调用实例方法load加载文件

4、通过_extensions解决不同文件

5、给文件加一个函数并自执行

6、解决屡次调用

7、返回module.exports

直接上代码:

const fs = require('fs');const path = require('path');const vm = require('vm');//虚拟机,可以到node官网文档理解//自己设置的require方法function myrequire(filename) { //解决路径 filename = Module._resolveFilename(filename); //判断能否有缓存 if(Module._cache[filename]){  return Module._cache[filename].exports; } //初始化实例 let module = new Module(filename); //进行加载 module.load(); Module._cache[filename] = module; //返回内容 return module.exports;}//缓存Module._cache = {}//构造函数,主要内容id(也就是路径做为id)和一个空对象function Module(id) { this.id = id; this.exports = exports;}//解决路径方法Module._resolveFilename = function (filename) { //生成绝对路径 let absPath = path.resolve(__dirname, filename); //fs方法,判断能否存在文件 if(fs.existsSync(absPath)){  return absPath; }else{  //引入有可能是require('./a'),没有后缀,手动拼接上判断  let keys = Object.keys(Module._extensions);  for(let i = 0; i< keys.length; i++){   let path = absPath + keys[i];   if(fs.existsSync(path)){    //不加后缀,寻觅到第一个直接返回,假如同名不同后缀不往下走    return path;   }  };  //假如都没有直接报错不存在  throw new Error('module is not exist'); }}//不同文件解决方法Module._extensions = { '.js'(module){  //同步读取文件  let content = fs.readFileSync(module.id, 'utf8');  //构造成一个函数  content = Module.wrapper[0] + content + Module.wrapper[1];  //使用runInThisContext变成不依赖上下文环境方法  let fn = vm.runInThisContext(content);  let exports = module.exports;  let dirname = path.dirname(module.id);  //调用方法,改变this  fn.call(exports, exports, myrequire, module, module.id, dirname); }, '.json'(module){  //直接可以返回  let content = fs.readFileSync(module.id, 'utf8');  module.exports = content; }}//js内容包裹成一个函数使用Module.wrapper = [ '(function(exports, require, module, __firname, __dirname){', '})']//加载方法Module.prototype.load = function () { //获取后缀,调用不同后缀方法 let extname = path.extname(this.id); Module._extensions[extname](this);}let a = myrequire('./a');let j = myrequire('./j');console.log(a);console.log(j);

node的方法上千行,我这只是学习一下大概原理,可以拷贝代码运行,而后了解了解。

image

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » node乞丐版require方法

发表回复