一、模块概念
Node.js是一个非常流行的服务器端JavaScript运行时环境,它可以在我们的服务器端直接运行JavaScript代码。在Node.js中,模块是一种用于组织和封装代码的技术。
模块:指解决一个复杂问题的时候,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来讲,模块是可以组合、分解和更换的单元。
在编辑领域中的模块,就是遵守固定的规则,把一个大文件拆成独立并且相互依赖的多个小模块。
代码进行模块拆分的好处有:提高代码的复用性,提高代码的可维护性,可以实现按需加载。
二、模块分类
1、内置模块
内置模块是由Node.js官方提供的
- fs 模块:用于文件操作,包括读取文件、写入文件、创建目录、删除文件等。
- http 模块:用于创建 HTTP 服务器和客户端,可以处理 HTTP 请求和响应。
- https 模块:与 http 模块类似,但支持安全的 HTTPS 协议。
- path 模块:用于处理文件路径,包括路径解析、拼接、规范化等。
- events 模块:用于实现事件驱动的编程,可以创建和处理事件。
- stream 模块:用于处理流式数据,可以读取和写入可流式的数据。
- util 模块:包含一些实用工具函数,如继承、类型判断、错误处理等。
- crypto 模块:提供加密和解密功能,包括哈希算法、对称加密和非对称加密等。
- os 模块:提供与操作系统相关的功能,如获取操作系统信息、处理文件路径等。
- querystring 模块:用于解析和序列化 URL 查询字符串。
2、自定义模块
每个用户创建的 .js文件,都是自定义模块
3、第三方模块
由第三方开发出来的模块,使用前需先下载,如:md5
三、加载模块
使用 require() 方法,可以加载需要的内置模块、自定义模块、第三方模块进行使用
注:使用 require() 方法加载其他模块时,会执行被加载模块中的代码。
模块在第一次加载后会被缓存,即多次调用require()方法不会导致模块的代码被执行多次。
不论是内置模块,用户自定义模块或第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。
1、加载内置模块
内置模块是由node.js官方提供的模块,内置模块的加载优先级最高。
const fs = require("fs");
2、加载自定义模块
当调用require()方法加载自定义模块时,必须指定以./或…/开头的路径标识符,如果没有路径标识符,则node.js会把它当作内置模块或第三方模块加载。
- 模块名中的.js可省略
- 相对路径与绝对路径皆可
const custom = require("./custom.js");
引入
require("./custom.js");
当我们在一个模块中引入其他模块时,我们可以直接使用被引入模块中导出的内容,而不需要使用模块名进行访问。
3、加载第三方模块
如果传递给require()的不是node.js的一个内置模块,也没有路径标识符,则node.js会从当前模块的父目录开始,尝试从/node_modules文件夹中加载第三方模块。
如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录中。
即从当前目录开始,寻找node_modules文件夹,找不到就从上级目录中找,直到文件根目录中,找到后就会加载对应的第三方模块。
const moment = require("moment")
四、导出模块
导出方法允许我们从一个模块中暴露出我们所希望的部分,以供其他模块使用。在Node.js中,模块中的导出方法通常有以下几种方式。
1、exports
该方法可以通过添加属性的方式导出,并且可以导出多个成员;
Node.js 提供了 exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。
//hello.js exports.world = () => { console.log('Hello World') } exports.add = (a, b) => { return a + b; } exports.person = { name: '张三', age: 20 }; exports.name = 'zrl'
在其他模块中使用
//index.js const {world,add,name,person} = require('./world') world() console.log(add(2,3)); console.log(name); console.log(person);
2、module.exports
最常用的导出方式是module.exports。通过将module.exports设置为一个函数、对象、类、常量等,我们可以在其他模块中使用它。只能导出单个成员。
- 例一
//world.js const Hello = ()=>{ let name this.setName = (val)=>{ name = val } this.sayHello = ()=>{ console.log("Hello " + name) } } module.exports = Hello
在其他模块中使用
const world = require('./world') let world = new world() world.setName('World') world.sayHello()
- 例二
//common.js const sum = (a, b) => { return a + b; } const PI = 3.14; function subtract(a, b) { return a - b; } module.exports = { add: add, subtract, PI };
在其他模块中使用
const {sum,PI,subtract} = require('./common') console.log(add(1, 2)); // 输出 3 console.log(subtract(5, 3)); // 输出 2 console.log(PI); // 输出 3.14
五、模块作用域
模块作用域:模块作用域和函数作用域类似,在自定义模块中定义的变量、方法只能在当前模块内被访问,这种模块级别的访问限制。模块作用域的好处可以防止全局变量污染的问题。
// 模块作用域 const username = "张三"; function funcs(){ console.log("大家好,我叫" + username); };