# 模块化的区别
# 1. CommonJS
# 1.1 Usage
// 导入
const someFun= require('./moduleA');
someFun();
// 导出
module.exports = someFunc;
# 1.2 特点
- CommonJS导出的是值的拷贝
- CommonJS中最开始引用模块时会加载,之后会缓存在cache变量中
TIP
CommonJS导出的是值的拷贝,这句话其实没有那么神秘,就按照正常js运行时的逻辑来思考就可以
- 模块输出的是对象,属性值是简单数据类型时:
//name.js
let name = 'William';
setTimeout(() => { name = 'Yvette'; }, 300);
module.exports = { name };
//index.js
const { name } = require('./name');
console.log(name); //William
//name 是一个原始类型的值,更改不会影响导出对象
setTimeout(() => console.log(name), 500); //William
模块输出的是对象:
//name.js
let name = 'William';
let hobbies = ['coding'];
setTimeout(() => {
name = 'Yvette';
hobbies.push('reading');
}, 300);
module.exports = { name, hobbies };
//index.js
const { name, hobbies } = require('./name');
console.log(name); //William
console.log(hobbies); //['coding']
/*
* name 的值没有受到影响,因为 {name: name} 属性值 name 存的是个字符串
* 300ms后 name 变量重新赋值,但是不会影响 {name: name}
*
* hobbies 的值会被影响,因为 {hobbies: hobbies} 属性值 hobbies 中存的是
* 数组的堆内存地址,因此当 hobbies 对象的值被改变时,存在栈内存中的地址并
没有发生变化,因此 hoobies 对象值的改变会影响 {hobbies: hobbies}
* xx = { name, hobbies } 也因此改变 (复杂数据类型,拷贝的栈内存中存的地址)
*/
setTimeout(() => {
console.log(name);//William
console.log(hobbies);//['coding', 'reading']
}, 500);
# 1.2 手写require
let fs = require('fs');
let path = require('path');
let b = myRequire('./b.js');
let cache = {}
function myRequire(mod) {
if (cache[mod]) return cache[mod]; // 缓存
let filename = path.join(__dirname, mod);
let content = fs.readFileSync(filename, 'utf8');
let fn = new Function('exports', 'require', 'module', '__filename', '__dirname', content + '\n return module.exports;');
let var module = (cache[mod] = {
exports: {},
});
return fn(module.exports, myRequire, module, __filename, __dirname);
}
# 2. ES6 模块化
# 2.1 Usage
// 导入
import { name } from './person.js';
// 导出
export const name = 'zfpx';
# 2.2 特点
- ES6 module导出的是值的引用
- ES6 模块是编译时输出接口
TIP
es6 中把module官方化了,那么import export 就是关键字了
对外接口只是一种静态定义,在代码静态解析阶段就会生成
//name.js
let name = 'William';
setTimeout(() => { name = 'Yvette'; hobbies.push('writing'); }, 300);
export { name };
export var hobbies = ['coding'];
//index.js
import { name, hobbies } from './name';
console.log(name, hobbies); //William ["coding"]
//name 和 hobbie 都会被模块内部的变化所影响
setTimeout(() => {
console.log(name, hobbies); //Yvette ["coding", "writing"]
}, 500); //Yvette
# 3. 区别
- CommonJS导出的是值的拷贝,ES6 module导出的是值的引用
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口