commonjs require原理

// let a = require('xxxx')
// 1.读取给定路径的文件里的内容,拿到字符串
//    -- 可能给了后缀,直接读
//    -- 可能没有给后缀,没有的话就按照顺序 .js .json .node优先级来加载文件
// 2.拿到绝对路径去缓存里查找一下,是否有加载过
//    -- 有就直接return
//    -- 没有创建这个模块,模块里有个this.exports对象
// 3.放如缓存
let path = require('path')
let fs = require('fs')
let vm = require('vm')

function Module(fullPath) {
    this.fullPath = fullPath;
    this.exports = {};
}

Module._extentions = ['.js', '.json', '.node'];
Module._cache = {};

Module._resovleFilename = function(relativePath){
    let p = path.resolve(__dirname, relativePath);
    let ext = path.extname(p);
    if (ext && Module._extentions[ext]) {
        // 写的是全路径
    } else {
        // 拼接
        for (let i = 0; i < Module._extentions.length; i++) {
            let fullPath = p + Module._extentions[i];
            try{
                fs.accessSync(fullPath);
                return fullPath
            }catch(e){
                console.log(e)
            }
        }
    }
}
Module.prototype.load = function(){
    // js加闭包,json直接当对象
    let ext = path.extname(this.fullPath)
    Module._extentions[ext](this);
}
Module.wrapper = ["(function(exports, module, require){" , "\n})"]
Module.wrap = function(script) {
    return Module.wrapper[0] + script +  Module.wrapper[1];
}
Module._extentions['.js'] = function(module){
    let codeText = fs.readFileSync(module.fullPath);
    let fnStr = Module.wrap(codeText)
    let fn = vm.runInThisContext(fnStr);
    fn.call(module.exports, module.exports, module, req)
}
Module._extentions['.json'] = function(module){
    let codeText = fs.readFileSync(module.fullPath);
    module.exports = JSON.parse(codeText)
}
function req(p) {
    // 搞出绝对路径
    let fullPath = Module._resovleFilename(p);
    // 拿到绝对路径去缓存里找
    if(Module._cache[fullPath]) {
      return Module._cache[fullPath];
    }
    // 没有缓存说明没有加载过
    let module = new Module(fullPath);
    module.load();
    Module._cache[fullPath] = module.exports;
    return module.exports
}

let a = req('./a')
console.log(a);

a.name = 'jack'
let bb = req('./a')
console.log(bb)


/* ***********引用传递,原来的那个会被改掉哦************ */
let a = require('./a')
console.log(a);//{ name: 1, age: 2 }


a.name = 'jack'
let bb = require('./a')
console.log(bb)//{ name: 'jack', age: 2 }
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值