本文主要自己觉得要记录的点记录下来,不耽误大家时间,会持续更新。
Module对象
Module {
id: 'xxx/demo/1.js', //加载文件的绝对路径
path: 'xxx/demo',// 加载文件所在目录的绝对路径
exports: [Function (anonymous)],
filename: 'xxx/demo/1.js',加载文件的绝对路径
loaded: false,// 是否加载完成
children: [],// 子模块
paths: [
'/xxx/xxx/xxx/xxx/xxx/src/pages/demo/node_modules',
'/xxx/xxx/xxx/xxx/node_modules',
'/xxx/xxx/xxx/node_modules',
'/xxx/xxx/node_modules',
'/xxx/node_modules',
'/node_modules'
]
}
CommonJS加载一次之后会缓存文件
加载过程
(function(exports, require, module, __dirname, __filename){
var load = function (exports, module) {
const aa = require('./demo);
const result = aa;
module.exports.result = result;
return module.exports;
};
var exported = load(module.exports, module);
save(module, exported);
})
CommonJS返回的是对象引用之后,在A地方修改后,会影响到B地址的加载结果。
CommonJS
模块同步加载并执行模块文件,ES6 模块提前加载并执行模块文件,ES6 模块在预处理阶段分析模块依赖,在执行阶段执行模块,两个阶段都采用深度优先遍历,执行顺序是子 -> 父。
CommonJS 父->子->父 (父加载 遇到引用了子,加载子,子加载完跳回父继续加载)
ES6 module 子->父 (父里面引用子,加载子,子里面引用子,加载子...加载完再一步一步返回上一级加载)
2 与 exports
相比,module.exports
有什么缺陷 ?
答:module.exports
当导出一些函数等非对象属性的时候,也有一些风险,就比如循环引用的情况下。对象会保留相同的内存地址,就算一些属性是后绑定的,也能间接通过异步形式访问到。但是如果 module.exports 为一个非对象其他属性类型,在循环引用的时候,就容易造成属性丢失的情况发生了。
这句话一直不理解直到看了下面这个例子:
a.js
const getMes = require('./b.js');
console.log('我是a文件');
// /**
// * @description: 写法一
// */
// exports.say = function () {
// const message = getMes();
// console.log(message);
// };
/**
* @description: 写法二
*/
const say = function () {
const message = getMes();
console.log(message);
};
module.exports = say;
b.js
const say = require('./a');
const obj = {
age: 10,
};
console.log('我是b文件', say);
setTimeout(() => {
console.log('setTimeout...', say);
}, 10);
module.exports = function () {
return obj;
};
main.js
require('./a.js');
require('./b.js');
写法1
b中第一次倒入的a模块对象say是一个空对象,然后a加载完毕exports(也就是b里面那个空对象的引用)赋值了一个属性say。所以setTimeout可以拿到属性say
写法2
b中第一次倒入的a模块对象say是一个空对象,然后a加载完毕module.exports重新赋值了一个新的对象,那之前的对象(也就是b中导入的那个对象)就应用是一个空对象。那么setTimeout里面自然也是一个空对象。如果在setTimeout重新导入a模块就能拿到改变之后的a模块。
//TODO。。。