外观
模块化 
一. 介绍 
将一个复杂的程序文件依据一定规则 (规范) 拆分成多个文件的过程称之为 模块化
其中拆分出的每个文件就是一个模块, 模块内部数据是私有的, 不过模块可以暴露内部数据以便其他模块使用。
好处:
- 防止命名冲突
- 高复用性
- 高维护性
二. 模块暴露数据 
1 模块初体验 
- me.js
js
function test() {
  console.log("test")
}
module.exports = test- index.js
js
const test = require("/me.js")
test()2 暴露数据 
- module.exports = value
- exports.name = value
注意事项
module.exports可以暴露任意数据- 不能使用
exports = value形式暴露数据, 模块内部module与exports的隐式关系exports = module.exports = {},require返回的是目标模块中module.exports的值
三. 导入模块 
const test = require('./me.js')
注意事项
- 对于自己创建的模块, 导入模块建议使用
相对路径, 且不省略./和../
js和json导入时可以不加后缀,c/c++编写的node拓展文件也可以不加后缀- 如果导入其他类型文件, 会以
js文件进行处理- 如果导入的路径是文件夹, 首先检测该文件夹下
package.json中的main属性对应的文件, 如果存在则导入, 否则如果文件不存在报错。如果main属性不存在, 或者package.json不存在, 则会尝试导入文件夹下index.js和index.json, 如果还是没找到, 就会报错- 导入
node.js内置模块, 直接require模块名字即可, 无需添加./和../
四、导入模块的基本流程 
- 将相对路径转为绝对路径, 定位目标文件
- 缓存检测
- 读取目标文件代码
- 包裹为一个函数并执行(立即执行函数), 通过arguments.callee.toString()查看自执行函数
- 缓存模块的值
- 返回module.exports的值
伪代码如下:
js
function require(file){
  //1. 将相对路径转为绝对路径,定位目标文件
  let absolutePath = path.resolve(__dirname, file);
  //2. 缓存检测
  if(caches[absolutePath]){
    return caches[absolutePath];
  }
  //3. 读取文件的代码
  let code = fs.readFileSync(absolutePath).toString();
  //4. 包裹为一个函数 然后执行
  let module = {};
  let exports = module.exports = {};
  (function (exports, require, module, __filename, __dirname) {
    const test = {
      name: 'alexshwing'
    }
    module.exports = test;
    console.log(arguments.callee.toString());
  })(exports, require, module, __filename, __dirname)
  //5. 缓存结果
  caches[absolutePath] = module.exports;
  //6. 返回 module.exports 的值
  return module.exports;
}五、CommonJS规范 
module.exports、exports以及require都是CommonJs模块化规范中的内容
Node.js实现CommonJS模块化规范, 二者关系像JavaScript与ECMAScript
 Alexshwing
Alexshwing