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()方法用于加载该模块
相关推荐
Rain5091 天前
mini-cc 的 MCP 协议:给 AI 装个 USB-C 接口
c语言·开发语言·前端·人工智能·架构·node.js·ai编程
YANQ6621 天前
7.bundlesdf本地安装
前端·webpack·node.js
代码N年归来仍是新手村成员1 天前
【AWS】Lambda 初识与服务部署
javascript·react.js·ai·node.js·云计算·ai编程·aws
wgc2k1 天前
Nest.js基础-4:Nest.js,游戏服务器,微服务架构
游戏·typescript·node.js
wgc2k1 天前
Nest.js基础-3:常用框架比较
typescript·node.js
乐于分享的阿乐2 天前
最新长期支持版本nodejs安装及环境配置(保姆级图文+安装包)
node.js
m0_535817552 天前
macOS上Claude Code安装配置保姆级教程:国内直连API,从0到1跑通(附避坑指南)
gpt·macos·ai·node.js·claude·claudecode·88api
五月君_2 天前
放弃 Python,Kimi 用 TS + Node.js 重写了一个 Kimi Code
开发语言·python·node.js
涛声依旧-底层原理研究所3 天前
Node.js在高并发低延迟场景中的优势
java·人工智能·python·node.js
晓杰'3 天前
从0到1实现Balatro游戏后端(5):得分计算与单局结算流程实现
后端·typescript·node.js·游戏开发·项目实战·nestjs·webscoket