一. 模块查找

1. 绝对路径

  • 根据绝对路径直接加载模块
  • 因为访问文件需要使用绝对路径, 其他方式只是编写代码的便捷写法, 所以其他模块查找方法, 最终都会转换为绝对路径.
  • ```javascript // require(“模块在系统中的绝对路径”)

require(“D:/Develop/demo/Node/src/a.js”)

require(“D:\Develop\demo\Node\src\a.js”)

  1. <a name="8c19c5c4"></a>
  2. ### 2. 相对路径 ./ 或 ../
  3. - 相对于当前模块
  4. - 转换为绝对路径
  5. - 加载模块
  6. -
  7. ```javascript
  8. // require("模块相对路径")
  9. require("./src/a.js")

3. 相对路径

  • 检查是否是内置模块, 如 fs, path 等

    • node安装之后本身自带的模块
  • 检查当前目录中的 node_modules
  • 检查上级目录中的 node_modules
  • 转换为绝对路径
  • 加载模块
  • ```javascript // require(“模块名称”)

// 例如: require(“abc”)

  1. <a name="95dcab23"></a>
  2. ### 4. 关于后缀名
  3. - 如果不提供后缀名, 则 node 会自动补全后缀名
  4. - js > json > node > mjs
  5. -
  6. ```javascript
  7. require("./src/a")

5. 关于文件名

  • 如果仅提供目录, 不提供文件名, 则自动寻找该目录中的 index.js
  • package.json 中的 main 字段

    • 表示包的默认入口
    • 导入或执行包时若仅提供目录, 则使用 main 补全入口
    • 默认值为 index.js
    • node_mobules 中的模块三方库, 也相同
      1. node ./

二. module 对象

  • 记录了当前模块的信息
  1. Module {
  2. id: '.', // 模块绝对路径, 如果是入口模块的话 id 为 ".", 而不是绝对路径
  3. path: 'D:\\Develop\\demo\\Node', // 模块的目录
  4. exports: {}, // 用于导出
  5. parent: null, // 被哪个模块使用
  6. filename: 'D:\\Develop\\demo\\Node\\index.js', // 模块的绝对路径
  7. loaded: false, // 模块是否加载完成
  8. children: [], // 子模块
  9. paths: [
  10. 'D:\\Develop\\demo\\Node\\node_modules',
  11. 'D:\\Develop\\demo\\node_modules',
  12. 'D:\\Develop\\node_modules',
  13. 'D:\\node_modules'
  14. ] // 记录了查找顺序
  15. }

三. require 函数

  1. [Function: require] {
  2. // 将任何的路径写法转换为绝对路径 (不加载模块, 只是获取绝对路径字符串)
  3. resolve: [Function: resolve] { paths: [Function: paths] },
  4. // 主模块, 入口起点用的是哪个模块
  5. main: Module {
  6. id: '.',
  7. path: 'D:\\Develop\\demo\\Node',
  8. exports: {},
  9. filename: 'D:\\Develop\\demo\\Node\\index.js',
  10. loaded: false,
  11. children: [],
  12. paths: [
  13. 'D:\\Develop\\demo\\Node\\node_modules',
  14. 'D:\\Develop\\demo\\node_modules',
  15. 'D:\\Develop\\node_modules',
  16. 'D:\\node_modules'
  17. ]
  18. },
  19. // 扩展名的处理函数
  20. extensions: [Object: null prototype] {
  21. '.js': [Function (anonymous)],
  22. '.json': [Function (anonymous)],
  23. '.node': [Function (anonymous)]
  24. },
  25. // 目前缓存的模块
  26. cache: [Object: null prototype] {
  27. 'D:\\Develop\\demo\\Node\\index.js': Module {
  28. id: '.',
  29. path: 'D:\\Develop\\demo\\Node',
  30. exports: {},
  31. filename: 'D:\\Develop\\demo\\Node\\index.js',
  32. loaded: false,
  33. children: [],
  34. paths: [Array]
  35. }
  36. }
  37. }

四. 当执行一个模块或使用 require 时, 会将模块放置在一个函数环境中

  • myModule.js

    • ```javascript console.log(‘当前模块路径 :>>’, dirname); console.log(‘当前模块文件 :>>’, filename); this.m = 5 exports.c = 3 module.exports = { a: 1, b: 2 }

// 被引用 输出 / 当前模块路径 :>> D:\Develop\demo\Node 当前模块文件 :>> D:\Develop\demo\Node\myModule.js result :>> { a: 1, b: 2 } /


console.log(‘当前模块路径 :>>’, dirname); console.log(‘当前模块文件 :>>’, filename); this.m = 5 module.exports.a = 1 module.exports.b = 2 exports.c = 3

// 被引用输出 / 当前模块路径 :>> D:\Develop\demo\Node 当前模块文件 :>> D:\Develop\demo\Node\myModule.js result :>> { m: 5, a: 1, b: 2, c: 3 } /

  1. - 模拟 require
  2. -
  3. ```javascript
  4. // 伪代码
  5. function require(modulePath) {
  6. // 1. 将 modulePath 转换为绝对路径 D:\Develop\demo\Node\myModule.js
  7. // 2. 判断是否该模块已有缓存
  8. if (require.cache = ["D:\\Develop\\demo\\Node\\myModule.js"]) {
  9. return require.cache = ["D:\\Develop\\demo\\Node\\myModule.js"].result
  10. }
  11. // 3. 读取文件内容
  12. console.log('当前模块路径 :>>', __dirname);
  13. console.log('当前模块文件 :>>', __filename);
  14. this.m = 5
  15. module.exports.a = 1
  16. module.exports.b = 2
  17. exports.c = 3
  18. // 4. 包裹到一个函数中
  19. function __temp(module, exports, require, __dirname, __filename) {
  20. console.log('当前模块路径 :>>', __dirname);
  21. console.log('当前模块文件 :>>', __filename);
  22. this.m = 5
  23. module.exports.a = 1
  24. module.exports.b = 2
  25. exports.c = 3
  26. }
  27. // 5. 创建 module 对象
  28. module.exports = {}
  29. const exports = module.exports
  30. __temp.call(module.exports, module, exports, require, module.path, module.filename) // 传入的 this 为 module.exports
  31. return module.exports
  32. }
  33. require.catch = {};
  34. const result = require("./myModule")
  35. console.log("result :>>", result);
  36. console.log(this === module.exports); // true
  37. console.log(this === exports); // true

注意:

  • 不建议直接操作 “this” , 在实际编码当中
  • 要么使用 “exports.属性”
  • 要么使用 “module.exports = {}”
  • this === exports === module.exports