CommonJS规范

模块化

  • 模块化解决的问题
    • 代码的数量增多导致编写程序复杂度越来越高,此时如果依然将所有的代码编写到同一个文件中,代码就会变得非常难以维护,模块化就说解决这个问题的关键。
  • 什么是模块?
    • 模块简单理解就是一个代码片段,本来写在一起的JS代码,我们按照不同的功能将它拆分成一个个小的代码片段,这个代码片段就是一个模块,简单来说,就是化整为零。
       
  • 模块化的好处
    • 模块化后不再是所有的代码写在一起,而是按照功能做了不同的区分,当维护代码时可以比较快捷的找到那些要修改的代码,
    • 模块化后,代码更容易被复用,同样一个模块可以在不同的项目中使用,大大降低开发成本

CommonJS

  • 在node中,默认支持的模块化规范就叫CommonJS
  • 模块就是一个JS文件,在模块内部任何变量或者其他对象都是私有的,不会暴露给外部模块,
  • 在CommonsJS模块化规范中,在模块内部定义了一个module对象,module对象内部存储了当前模块的基本信息,同时module对象中有一个属性名exports,exports用来指定需要向外部暴露的内容,只需要将需要暴露的内容设置为exports或exports的属性,其他模块即可通过require来获取这些内容

CommonsJS规范

  • 引入模块
    • 使用require("模块的路径")函数来引入模块
    • 引入自定义模块时
      • 模块名要使用 ./ 或  ../开头
      • 扩展名可以省略不写  ("./m1.js") 中的 .js  就是扩展名
      • 在CommonJS中,如果省略的js文件的扩展名,则node会自动为文件补全拓展名,
      • 访问文件,优先访问 .js 结尾的文件 ,其次是 .json 结尾的文件, 最后是 .node 结尾的文件
// 引入文件名为m1的模块
const file = require("./m1.js")
console.log(file)
  • 在定义模块时,模块中的内容默认是不能被外部看到的
    • 可以通过exports来设置要向外暴露的内容
  • 访问exports的方式有两种:
    • exports
    • module.exports
    • 当我们在其他模块中引入当前模块时,require函数的返回的就是exports
    • 可以将希望暴露给外部模块的内容设置为exports的属性

通过exports一个一个的导出值

m1.js文件

// 通过exports向外界暴露a b c 三个变量
exports.a = "孙悟空"
exports.b = "猪八戒"
exports.c = "沙和尚"

01_模块化.js文件

// 引入文件名为m1的模块
const file = require("./m1.js")
// 打印输出
console.log(file)

打印结果 

{a: '孙悟空', b: '猪八戒', c: '沙和尚'}

通过module.exports同时导出多个值

m1.js文件


// 通过module.exports同时导出多个值
module.exports = {
    a: "哈哈",
    b: [1, 1],
    c: () => {
        console.log(111)
    }

}

01_模块化.js文件

// 引入文件名为m1的模块
const file = require("./m1.js")
// 打印输出
console.log(file)

 打印结果 

{a: '哈哈', b: Array(2), c: ƒ}
  • 引入核心模块时
    • 直接写核心模块的名字即可
    • 也可以在核心模块前添加node: ,加快查找速度
// 引入内置的核心模块"path"
const path = require("path")

// 引入内置的核心模块"path"
// 加 node: 是为了指明是核心模块
const path = require("node:path")

默认情况下,Node.js会将以下的内容视为CommonJS模块:

  1. 使用 .cjs为扩展名的文件
  2. 当前的package.json的type属性为commonjs时,扩展名为 .js 的文件
  3. 当前的 package.json不包含type属性时,扩展名为 .js 的文件
  4. 文件得到扩展名是mjs、cjs、node、js意外的值时(type不是module时)

require() 是同步加载模块的方法,所以无法用来加载ES6的模块,当我们需要在CommonJS中加载ES模块时

模块的包装

每一个CommonJS模块在执行时,外层都会被套上一个函数


(function(exports,require,module, _filename, _dirname) {
// 模块代码会被放到这里
});

模块都是包含在函数当中的

// 所写的模块
let a = 20
let b = 10 

// 在执行时是套在模块里面的
(function(exports,require,module, _filename, _dirname) {
    // 模块代码会被放到这里
    let a = 20
    let b = 10 
});

证明模块确实运行到了函数里面,使用函数专有的arguments, 所有的实参都会封装到 arguments 中

// 所写的模块
let a = 20
let b = 10 

// 打印arguments 观测模块是否运行到了函数里面
console.log(arguments)

控制台打印

Arguments(5) [{…}, ƒ, Module, 'D:\前端\NodeJs\02_模块化\m1.js', 'D:\前端\NodeJs\02_模块化', callee: ƒ, Symbol(Symbol.iterator): ƒ]

所以我们之所以能在CommonJS中模块中使用exportsrequire并不是因为他们是全局变量,他们实际上以为参数的形式传递模块

exports: 用来设置模块向外暴露的内容

require: 用来引入模块的方法

module: 当前模块的引用

__filename: 模块的路径

__dirname: 模块所在目录的路径

你可能感兴趣的:(node.js)