模块化规范
1.CommonJS规范
在node中,默认支持的模块化规范叫做CommonJS,
在CommonJS中,一个js文件就是一个模块
-
CommonJS规范
-
引入模块
-
使用require('模块的路径')函数来引入模块
-
引入自定义模块时
- 模块名要以 ./ 或 ../ 开头
- 扩展名可以省略
- 在CommonJS中,如果省略的js文件的扩展名,node会自动不全扩展名
- 如果没有改js文件,会找名字相同的文件进行引入
- 在CommonJS中,如果省略的js文件的扩展名,node会自动不全扩展名
-
引入核心模块时
- 直接写核心模块的名字即可
- 也可以在核心模块前添加
node:
可以加快查询效率
-
//引入自定义模块 const m1 = require("./m1") //按需引入 const name = require('./m1').name const {name,age,gender} = require('./m1') //引入核心模块 const path = require("path") const path = require("node:path")
在定义模块时,模块中的内容默认是不能被外部看到的
可以通过exports来设置要向外部暴露的内容
访问exports的方式有两种:
- exports
- module.exports
- 当我们在其他模块中引入当前模块时,require函数返回的就是exports -
- 可以将希望暴露给外部模块的内容设置为exports的属性
------------------------------m1.js---------------------------------------- // 可以通过exports 一个一个的导出值 // exports.a = "孙悟空" // exports.b = {name:"白骨精"} // exports.c = function fn(){ // console.log("哈哈") // } // 也可以直接通过module.exports同时导出多个值 module.exports = { a: "哈哈", b: [1, 3, 5, 7], c: () =>{ console.log(111) } }
CommonJS执行原理:
-
所有的CommonJS的模块都会被包装到一个函数中
(function(exports, require, module, __filename, __dirname){ //模块代码会被放到这里 })
exports
:用来设置模块向外部暴露的内容require
:用来引入模块的方法module
:当前模块的引用__filename
:模块的路径__dirname
:模块所在目录的路径
-
2.ES6模块化
Node.js中同样支持ES模块化,使用模块化无非就是需要注意两件事导出和导入
-
导出
// 导出变量(命名导出) export let name1, name2, …, nameN; export let name1 = …, name2 = …, …, nameN; // 导出函数(命名导出) export function functionName(){...} // 导出类(命名导出) export class ClassName {...} // 导出一组 export { name1, name2, …, nameN }; // 重命名导出 export { variable1 as name1, variable2 as name2, …, nameN }; // 解构赋值后导出 export const { name1, name2: bar } = o; // 默认导出 export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; // 聚合模块 export * from …; // 将其他模块中的全部内容导出(除了default) export * as name1 from …; // ECMAScript® 2O20 将其他模块中的全部内容以指定别名导出 export { name1, name2, …, nameN } from …; // 将其他模块中的指定内容导出 export { import1 as name1, import2 as name2, …, nameN } from …; // 将其他模块中的指定内容重命名导出 export { default, … } from …;
-
引入
// 引入默认导出 import defaultExport from "module-name"; // 将所有模块导入到指定命名空间中 import * as name from "module-name"; // 引入模块中的指定内容 import { export1 } from "module-name"; import { export1 , export2 } from "module-name"; // 以指定别名引入模块中的指定内容 import { export1 as alias1 } from "module-name"; import { export1 , export2 as alias2 , [...] } from "module-name"; // 引入默认和其他内容 import defaultExport, { export1 [ , [...] ] } from "module-name"; import defaultExport, * as name from "module-name"; // 引入模块 import "module-name";
需要注意的是,Node.js默认并不支持ES模块化,如果需要使用可以采用两种方式:
- 方式一:直接将所有js文件修改为mjs扩展名。
- 方式二:修改package.json中type属性为module。
3.核心模块
核心模块,是node中自带的模块,可以在node中直接使用
- window 是浏览器的宿主对象 node中是没有的
- global 是node中的全局对象,作用类似于window
- ES标准下,全局对象的标准名应该是
globalThis
-
process
-
表示当前的node进程
-
可以通过改对象获取进程的信息,或者对进程做各种操作
-
如何使用
-
process是一个全局变量,可以直接使用
-
有哪些属性和方法:
-
process.exit([code状态码])
- 结束当前进程,终止node
-
process.nextTick(callback[ ...args])
-
将函数插入到 tick队列中
-
tick队列中的代码,会在下一次事件循环之前执行,会在微任务队列和宏任务队列中任务之前执行
setTimeout(()=>{ console.log('111') }) //宏任务队列 queueMicrotask(()=>{ console.log('222') }) //微任务队列 process.nextTick(()=>{ console.log('333') }) console.log('444') //执行顺序为: 444 -> 333 -> 222 -> 111
-
-
执行顺序:
- 调用栈
- tick队列(了解)
- 微任务队列
- 宏任务队列
-
-
-
path模块
-
表示的路径
-
通过path可以用来获取各种路径
-
要使用path,需要先对其进行引入
-
方法:
-
path.resolve([...paths])
- 用来生成一个绝对路径
- 直接调用resolve,则返回当前的工作目录
- 注意,我们通过不同的方式执行代码时,它的工作目录是有可能发生变化的
-
如果将一个相对路径作为参数:
- 则resolve会自动将其转换为绝对路径
- 此时根据工作目录的不同,他所产生的绝对路径也不同
-
一般会将一个绝对路径作为第一个参数
- 一个相对路径作为第二个参数
- 这样它会自动计算出最后的路径
//引入模块 const path = require('node:path') //以后在使用路径时,尽量通过path.resolve()来生成路径 const result = path.resolve(__dirname, './hello.js')
-
-
-
fs模块
-
fs用来帮助node来操作磁盘中的文件
-
文件操作也就是所谓的I/O流,input output
-
使用fs模块,同样需要引入
-
fs.readFileSync()
-
readFileSync() 同步的读取文件的方法,会阻塞后面的代码执行
-
当我们通过fs模块读取磁盘中的数据时,读取到的数据总会一Buffer对象的形式返回
-
Buffer是一个临时用来存储数据的缓冲区
//引入模块 const path = require('node:path') const fs = require('node:fs') const buffer = fs.readFileSync(path.resolve(__dirname, './hello.txt')) console.log(buffer.toString()) //把Buffer数据转换为字符串类型
-
-
fs.readFile()
-
异步的读取文件的方法
-
方法1:回调函数式
const path = require('node:path') const fs = require('node:fs') fs.readFile(path.resolve(__dirname, './hello.js'),(err,buffer)=>{ if(err){ console.log("出错了~") } else { console.log(buffer.toString()) } })
-
方法2:promise式
const path = require('node:path') const fs = require('node:fs/promises') fs.readFile(path.resolve(__dirname, './hello.js')) .then(buffer=>{ console.log(buffer.toString()) }) .catch(e=>{ console.log('出错了,有问题', e.message) })
-
方法3:async和await式
;(async ()=>{ try { const buffer = await fs.readFile(path.resolve(__dirname, './hello.js')) console.log(buffer.toString()) } catch(e){ console.log(’出错了....) } })()
-
-
-
fs.appendFile()
- 创建新文件,或将数据添加到已有文件中
-
fs.mkdir()
- 创建目录
-
fs.rmdir()
- 删除目录
-
fs.rm()
- 删除目录
-
fs.rename()
- 重命名
-
fs.copyFile()
- 复制文件
-
-
//实现复制一个文件 //1.读取文件中的内容 const path = require('node:path') const fs = require('node:fs/promises') fs.readFile(path.reslove(__dirname, './hello.txt')) .then(buffer =>{ //2.复制文件中的 return fs.appendFile(path.resolve(__dirname, './world.txt'), buffer) }) .then(()=>{ console.log('操作结束') }) .catch(err =>{ console.log('出错了..') })