NodeJS-模块化

266 阅读5分钟

模块化

模块化的概念

模块化 是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。

编程领域的模块化

编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并相互依赖的多个小模块。

把代码进行模块化拆分的好处:

  1. 提高了代码的复用性
  2. 提高了代码的可维护性
  3. 可以实现按需加载

模块化规范

模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。

例如:

  • 使用什么样的语法格式来引用模块
  • 在模块中使用什么样的语法格式向外暴露成员

模块化规范的好处:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用,利人利己。

Node.js中的模块化

Node.js中模块的分类

Node.js 中根据模块来源的不同,将模块分为了 3大类,分别是:

  • 内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http等)
  • 自定义模块(用户创建的每个 .js 文件,都是自定义模块)
  • 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)

加载模块

使用强大的 require() 方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。

// 1.加载内置的 fs模块
const fs=require('fs')

// 2.加载用户的自定义模块
// 注意:在使用 require 加载用户自定义模块期间,可以省略 .js 的后缀名
const m1=require('./14.m1')  // 给定一个路径
console.log(m1)  // m1默认是个空对象

// 3.加载第三方模块(会提前下载)
const moment=require('moment')

1.png

2.png

3.png

注意:使用 require() 方法加载其他模块时,会执行被加载模块中的代码。

Node.js 中的模块作用域

  1. 什么是模块作用域

    和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域

  2. 模块作用域的好处

    防止了全局变量污染的问题

4.png

5.png

6.png

向外共享模块作用域中的成员

1.module 对象

在每个 .js 自定义模块中都有一个 module 对象,它里面存储了和当前模块有关的信息,打印如下:

console.log(module)

8.png

2.module.exports 对象

在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用。

外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象。

// 17.自定义模块.js
// 在一个自定义模块中,默认情况下,module.exports={}

const age = 20
// 向  module.exports 对象上挂载 username 属性 
module.exports.username = '张三'

// 向  module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function () {
    console.log('Hello!')
}

module.exports.age = age   // 如果将这行代码注销,那么它就不会被拿到,就是私有的
// 在外界使用 require 导入一个自定义模块的时候,得到的成员,
// 就是 那个模块中,通过 module.exports 指向的那个对象
const m = require('./17.自定义模块')
console.log(m)

9.png

3.共享成员时的注意点

使用 require() 方法导入模块时,导入的结果,永远 以 module.exports指向的对象为准 。

// 17.自定义模块.js
// 在一个自定义模块中,默认情况下,module.exports={}

const age = 20
// 向  module.exports 对象上挂载 username 属性 
module.exports.username = '张三'

// 向  module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function () {
    console.log('Hello!')
}

module.exports.age = age

// 让module.exports 指向一个新对象
module.exports = {
    nickname: '小黑',
    sayHi() {
        console.log('Hi!')
    }
}
// 在外界使用 require 导入一个自定义模块的时候,得到的成员,
// 就是 那个模块中,通过 module.exports 指向的那个对象
const m = require('./17.自定义模块')
console.log(m)
4.exports 对象

由于 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports对象。 默认情况下,exports 和 modules.exports 指向同一个对象。最终共享的结果,还是以 module.exports 指向的对象为准。

console.log(module.exports)
console.log(module.exports)
console.log(module.exports === exports)

image-20250630163520392转存失败,建议直接上传图片文件

// console.log(module.exports)

// console.log(module.exports)

// console.log(module.exports === exports)

const username = '张三';
module.exports.username = username;

exports.age = 20

exports.sayHello = function () {
    console.log('say Hello!')
}

// 最终,向外共享的结果,永远都是 module.exports 所指向的对象

image-20250630164427959转存失败,建议直接上传图片文件

image-20250630164441916转存失败,建议直接上传图片文件

5.exports 和 module.exports 的使用误区

时刻谨记,require() 模块时,得到的永远是 module.exports 指向的对象:

image-20250630170238117转存失败,建议直接上传图片文件

注意:为了防止混乱,建议不要在同一个模块中同时使用 exports 和 module.exports

Node.js 中的模块化规范

Node.js 遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖

CommonJS规定:

  1. 每个模块内部,module 变量代表当前模块
  2. module 变量是一个对象,它的 exports 属性(即module.exports)是对外的接口
  3. 加载某个模块,其实是加载该模块的 module.exports属性。require()方法用于加载模块。