Node.js(三)——模块化

一、什么是模块化

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

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

1.模块化的好处:

  • 提高了代码的可维护性
  • 提高了代码的复用性
  • 可以实现按需加载

2.模块化规范的规则:

使用统一的规则方便各大模块的互相调用(使用什么语法来引入或者向外暴露)

二.node.js中的模块化

1.node.js模块的分类

  • 内置模块(fs、path、http)
  • 自定义模块(用户创建的每个js文件都是自定义模块,js在node里跑就是自定义模块,在浏览器跑就是普通js文件。用module.exports、require这些都是遵循的node规则)
  • 第三方模块(第三方开发出来的模块,使用之前需要先下载,npm的那些,什么axios、jquery这些都是)

内置和自定义的都在自己电脑上,第三方的就需要先下载才能使用,这是他们的区别

2.模块的加载

使用强大的require(),可以引入内置、自定义、第三方的模块进行使用

复制代码
const fs=require('fs')
const clock=require('./clock.js')
const moment=require('moment')

只有自定义模块需要路径

使用require加载其他模块的时候,会执行被加载模块中的代码

使用require加载自定义模块的时候,js后缀可以省略

3.node.js的模块作用域

与函数作用域相似,模块作用域里定义的变量和方法只能在当前模块被访问,这种模块级别的访问限制叫模块作用域。(只能在自己文件访问自己的变量和方法)

模块作用域的好处:防止全局变量被污染

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

1.module对象

每个自定义模块都有一个module对象,他存储了当前模块有关的信息

比如我们随便创建一个js文件,然后打印一下它里面的module

复制代码
console.log(module)

2.module.exports对象

从上面的截图可以看到exports默认是一个空对象,在自定义模块中,module.exports可以将模块中的成员共享出去供外界使用。然后外界使用require引入这个模块之后就可以拿到这个模块exports指向的对象。

module.exports默认是空对象,当module2文件里什么都没有的时候,a输出的是{},也就是mudule2中的module.exports对象

复制代码
const a=require('./module2.js')

console.log(a)

如果我们想共享一些东西出去的话,就只需要给mudule2中的module.exports对象赋值即可,比如:

复制代码
module.exports={
  username:'hh',
  sayHi(){
    console.log('aa')
  }
}

这里面写什么,require输出得到的就是什么,引入的文件输出:

我这里犯了一个错误,这里输出结果是aa undefined,我最开始纳闷undefined是哪来的,再一看发现console.log一个函数的话会先调用这个函数,然后打印出它的返回值

复制代码
const a=require('./module2.js')

console.log(a.sayHi())

就等同于下面这样,运行完a.sayHi()(这个过程会输出aa),然后把结果赋值给了result(没有return就是undefined)然后输出

复制代码
const a=require('./module2.js')

const result=a.sayHi()

console.log(result)

或者用module.exports.username='aa'这种方式赋值也可以

3.exports对象

由于module.exports对象写起来比较复杂,node提供了exports对象,默认情况下,exports对象就等同于module.exports,不过还是以module.exports指向的对象为准。

注意:require()得到的永远都是module.exports指向的对象

复制代码
// Node.js 每个模块开始前,会悄悄执行这两行
var module = { exports: {} }
var exports = module.exports   // exports 是 module.exports 的引用

所以像下面这个require得到的就是name 'hh',而不是那一大坨

复制代码
module.exports.name='hh'

exports={
  username:'hh',
  sayHi(){
    console.log('aa')
    return '88'
  }
}

在第一句执行完之后module.exports.name='hh',exports和module.exports都指向name 'hh'这个对象,然后下面的赋值让exports指向了别的对象,所以别的模块去require的时候得到的东西就跟exports无关了,所以建议不要在一个模块中用两种写法。

其实就只要记住这俩最开始指向一个对象,最后require得到的是module.exports指向的对象就可以了。

四.Node.js中的模块化规范

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

CommonJS规定:

  • 每个模块内部,module变量代表当前模块
  • module变量是一个对象,他的exports属性(即module.exports)是对外的接口
  • 加载某个模块,其实是加载该模块的moudle.exports属性,require()方法用于加载该模块
相关推荐
用户64340495148512 小时前
Elpis 项目构建工具与前端基建实践总结
node.js
FungLeo2 小时前
成为全栈·Node 后端篇·后端测试策略:单元、集成与测试数据库
单元测试·node.js·集成测试·测试策略·成为全栈·测试数据库
FungLeo3 小时前
成为全栈·Node 后端篇·评论内容安全:敏感词过滤、三态审核与级联删除
node.js·敏感词过滤·成为全栈·评论内容安全·评论审核·级联删除
FungLeo13 小时前
成为全栈·Node 后端篇·阅读量防刷:去重、冷却与计数写分离
node.js·读写分离·数据去重·接口防刷·成为全栈·数据冷却
脉动数据行情11 天前
Node.js WebSocket 实现贵金属实时行情监听 伦敦金 / 伦敦银自动重连方案
websocket·node.js·vim
不老刘1 天前
一行命令解决 Node.js 版本兼容问题:`--openssl-legacy-provider` 深度解析
node.js
万敏2 天前
Vue3 全栈实战:第一阶段复盘(第1-8周)
vue.js·node.js·全栈
濮水大叔2 天前
舒服了,CabloyJS 的 AI Spec 驱动开发会自动生成甘特图和燃尽图
typescript·node.js·vibecoding
FungLeo2 天前
成为全栈·Node 后端篇·部署上线:从本地起服到真正对外服务
node.js·后端部署·成为全栈
妙码生花2 天前
golang 应用服务端部署(使用 systemd 服务)
开发语言·人工智能·后端·golang·node.js·php·gin