Node.js的模块化

本文详细介绍了Node.js中的模块化概念,包括内置模块、自定义模块的模块作用域与导出机制,以及第三方模块(包)的使用和加载流程。重点讲解了如何避免混淆并有效管理模块间的交互。

目录

1什么是模块化

2Node中的模块化

3模块的加载机制


1什么是模块化

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

拆分后提高了代码的复用性,可维护性和按需加载。

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

2Node中的模块化

分为三大模块,内置模块(fs,path,http前面已经讲过,因此不再赘述),自定义模块(主讲),第三方模块(包的概念)。

const fs=require('fs')
const custom=require('./custom.js')
const moment=require('moment')

其中我们需要注意的是在自定义模块中的变量方法,只能被当前模板内访问。因此叫做模块作用域,其实和函数作用域类似。好处是防止了全局变量污染的问题。

 然后再来讨论自定义模块,在每个自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息。在自定义模块中,可以使用module.export对象,把模块内的成员共享出去,供外界使用。外界用require()方法导入自定义模块时,得到的就是module,exports所指向的对象。就下面代码为例,即使你给module挂载了多个属性,但是最终永远以module.exports所指向的对象为准。

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

const age = 20

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

// 让 module.exports 指向一个全新的对象
module.exports = {
  nickname: '小黑',
  sayHi() {
    console.log('Hi!')
  }
}

const m = require('./11.自定义模块')

console.log(m)//{ nickname: '小黑', sayHi: [Function: sayHi] }

以下演示4段代码,更加清晰的明确其中的关系。

exports.username = 'zs'
module.exports = {
        gender: '男',
        age: 22
    } //{gender:'男',age:22}

module.exports.username = 'zs'
exports = {
        gender: '男',
        age: 22
    } //{username:'zs'}

exports.username = 'zs'
module.exports.gender = '男' //{username:'zs',gender:'男'}

exports = {
    username: 'zs',
    gender: '男'
}
module.exports = exports
module.exports.age = '22' //{username:'zs',gender:'男',age:'22'}

因此为了防止混乱,最好不要在一个JS文件中,同时用exports和module.exports

CommonJS规定:每个模块内部,module变量代表当前模块。它的属性exports是对外的接口,加载某个模块,实际上是加载该模块的module.exports属性,用require方法加载模块。


第三方模块又称为包。包是基于Node内置模块封装出来的,类似于jQuery是基于浏览器内置API一样的关系。那么包有什么用呢?下面放一段代码用来格式化时间。一种方法是自定义模块,另一种方法是采用包moment,具体用法可以参考API官方文档

// 1. 定义格式化时间的方法
function dateFormat(dtStr) {
  const dt = new Date(dtStr)

  const y = dt.getFullYear()
  const m = padZero(dt.getMonth() + 1)
  const d = padZero(dt.getDate())

  const hh = padZero(dt.getHours())
  const mm = padZero(dt.getMinutes())
  const ss = padZero(dt.getSeconds())

  return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}

// 定义补零的函数
function padZero(n) {
  return n > 9 ? n : '0' + n
}

module.exports = {
  dateFormat
}


// 导入自定义的格式化时间的模块
const TIME = require('./15.dateFormat')

// 调用方法,进行时间的格式化
const dt = new Date()
console.log(dt)//2021-07-22T11:55:39.349Z
const newDT = TIME.dateFormat(dt)
console.log(newDT)//2021-07-22 19:54:24 




// 1. 导入需要的包
// 注意:导入的名称,就是装包时候的名称
const moment = require('moment')

const dt = moment().format('YYYY-MM-DD HH:mm:ss')
console.log(dt)

需要注意的是我们需要的第三方包和内置模块都是放在node_modules里面的,因此在我们拿到别人的项目后,需要使用nmp install命令,下载node_modules里面的所有内容,因为别人给的项目里面是不会包含node_modules这个文件夹的,所以我们需要自己下载。

3模块的加载机制

模块在第一次加载后会被缓存,这也意味着多次调用require不会导致模块的代码被执行多次。他们都会优先从缓存中加载,从而提高模块的加载效率。并且内置模块的优先级更高,也就是说即使我们自定义模块名为fs 实际上使用的还是内置模块fs。

对于自定义模块的加载机制,如果require时省略了文件的扩展名,则node会尝试js,json,node这三种扩展名进行加载,如果找不到就会报错。

对于第三方模块的加载机制,如果在当前模块的父目录下没有找到对应的文件,则会移动到再上一层父目录中,进行加载。直到找到根目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清辞-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值