From 82e53ca6cf24897d7e2d46633bdcd2c41a0a9999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E4=BB=81=E9=94=90?= <1377043985@qq.com> Date: Sun, 22 Mar 2026 20:16:03 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\347\275\256\346\250\241\345\235\227.md" | 246 ++++++++++++++++++ ...07\344\273\266\347\263\273\347\273\237.md" | 98 +++++++ ...41\345\235\227\347\273\203\344\271\240.md" | 68 +++++ .../20260320-HTML\346\250\241\346\235\277.md" | 66 +++++ 4 files changed, 478 insertions(+) create mode 100644 "\345\206\257\344\273\201\351\224\220/20260316-\345\206\205\347\275\256\346\250\241\345\235\227.md" create mode 100644 "\345\206\257\344\273\201\351\224\220/20260318-\346\226\207\344\273\266\347\263\273\347\273\237.md" create mode 100644 "\345\206\257\344\273\201\351\224\220/20260319-\346\226\207\344\273\266\347\263\273\347\273\237\346\250\241\345\235\227\347\273\203\344\271\240.md" create mode 100644 "\345\206\257\344\273\201\351\224\220/20260320-HTML\346\250\241\346\235\277.md" diff --git "a/\345\206\257\344\273\201\351\224\220/20260316-\345\206\205\347\275\256\346\250\241\345\235\227.md" "b/\345\206\257\344\273\201\351\224\220/20260316-\345\206\205\347\275\256\346\250\241\345\235\227.md" new file mode 100644 index 00000000..542435fd --- /dev/null +++ "b/\345\206\257\344\273\201\351\224\220/20260316-\345\206\205\347\275\256\346\250\241\345\235\227.md" @@ -0,0 +1,246 @@ +# 笔记 + +## 一、内置模块核心认知 + +### 1. 学习意义 + +Node.js 内置模块是满足日常开发核心需求的基础能力(如彩色日志、命令行参数、文件路径处理等),无需安装即可直接使用,是编写 Node.js 程序的必备基础。 + +### 2. 核心特点 + +- 无需安装:直接通过 `require` 引入,Node.js 自带; +- 高性能:底层由 C/C++ 编写,执行效率高; +- 功能全面:覆盖文件、网络、进程、二进制数据等场景; +- 稳定可靠:经过长期测试,生产环境可用。 + +## 二、四大核心内置模块详解 + +### 1. console 模块:增强版日志输出 + +核心能力是多样化、可视化的信息输出,常用方法: +| 分类 | 关键方法 | 用途 | +|------------|-----------------------------------|--------------------------| +| 基础输出 | log/info/warn/error | 不同级别日志(可区分场景) | +| 格式化输出 | %s(字符串)/%d(数字)/%j(JSON) | 精准控制输出格式 | +| 高级功能 | table、count、time/timeEnd、trace | 表格展示、计数、计时、调用栈追踪 | +| 校验 | assert | 断言判断(条件不满足时输出提示) | + +### 2. process 模块:进程与系统交互 + +核心是获取进程/系统信息、控制进程生命周期、处理命令行参数: + +- **进程信息**:`version`(Node 版本)、`platform`(系统平台)、`cwd()`(当前工作目录)、`env`(环境变量); +- **进程控制**:`exit()`(退出程序)、监听 `exit/SIGINT/uncaughtException` 事件(处理退出、中断、异常); +- **命令行参数**:`process.argv` 获取参数数组(前两项为 Node 路径/脚本路径,`slice(2)` 可提取自定义参数)。 + +### 3. Buffer 模块:二进制数据处理 + +Node.js 特有类型,专门处理文件读写、网络传输等场景的二进制数据: + +- **创建方式**:`Buffer.from()`(字符串/数组)、`Buffer.alloc()`(指定长度,初始化 0)、`Buffer.allocUnsafe()`(指定长度,不初始化,速度更快); +- **核心操作**:`toString()`(转字符串,可指定编码/截取范围)、`write()`(写入数据)、`concat()`(拼接 Buffer)、`length`(获取字节长度,中文占 3 字节)。 + +### 4. path 模块:文件路径处理 + +解决不同系统路径格式差异问题,核心方法: +| 功能 | 关键方法 | 用途 | +|--------------|-----------------------------------|--------------------------| +| 路径拼接/解析 | join()(拼接路径)、resolve()(转绝对路径) | 兼容不同系统路径分隔符 | +| 路径拆解 | basename()(文件名)、extname()(扩展名)、dirname()(目录)、parse()(解析路径对象) | 提取路径各部分信息 | +| 辅助判断 | isAbsolute()(判断绝对路径)、equals()(比较路径) | 路径合法性校验 | +| 常用变量 | **dirname(当前文件目录)、**filename(当前文件完整路径) | 快速获取文件相关路径 | + +## 三、实战应用场景 + +通过 4 个实操案例掌握模块用法: + +1. **信息展示程序**:用 `process` 模块输出 Node 版本、系统平台、工作目录等信息; +2. **彩色日志工具**:结合 `console` 模块实现带颜色、时间戳的分级日志(info/warn/error); +3. **命令行参数处理**:解析 `process.argv` 实现 add/delete/list 等自定义命令; +4. **Buffer 数据处理**:完成字符串与 Buffer 互转、拼接、写入等操作。 + +### 总结 + +1. Node.js 内置模块是基础核心能力,无需安装、性能高,覆盖日志、进程、二进制、路径四大高频场景; +2. console 侧重多样化输出,process 侧重进程/命令行交互,Buffer 处理二进制,path 解决路径兼容; +3. 核心高频用法:console.table/time、process.argv/cwd、Buffer.from/concat、path.join/resolve 是日常开发必用。 + +# 练习 + + 操作题 +信息展示:创建一个程序,输出当前系统的所有环境变量。 +// 遍历process.env对象,输出所有环境变量 +console.log('=== 系统环境变量 ==='); +for (const [key, value] of Object.entries(process.env)) { +console.log(`${key}: ${value}`); +} + +参数解析:创建一个计算器程序,支持: +node calc.js add 5 3 → 输出 8 +node calc.js sub 5 3 → 输出 2 +node calc.js mul 5 3 → 输出 15 +// 获取自定义参数(去除前两项) +const args = process.argv.slice(2); +// 校验参数数量 +if (args.length < 3) { +console.error('用法:node calc.js [add/sub/mul] 数字1 数字2'); +process.exit(1); +} +const [command, num1Str, num2Str] = args; +// 转换为数字并校验 +const num1 = Number(num1Str); +const num2 = Number(num2Str); +if (isNaN(num1) || isNaN(num2)) { +console.error('数字参数必须是有效数字!'); +process.exit(1); +} +// 执行计算 +let result; +switch (command) { +case 'add': +result = num1 + num2; +break; +case 'sub': +result = num1 - num2; +break; +case 'mul': +result = num1 \* num2; +break; +default: +console.error('支持的命令:add(加)、sub(减)、mul(乘)'); +process.exit(1); +} +console.log(`结果:${result}`); +//测试 +node calc.js add 5 3 # 输出 8 +node calc.js sub 5 3 # 输出 2 +node calc.js mul 5 3 # 输出 15 + +Buffer操作:创建一个程序,将中文字符串转为Buffer,再转回字符串,验证是否一致。 +// 定义中文字符串 +const chineseStr = 'Node.js内置模块学习'; +// 转Buffer +const buf = Buffer.from(chineseStr, 'utf8'); +console.log('Buffer数据:', buf); +console.log('Buffer长度(字节):', buf.length); +// Buffer转回字符串 +const str = buf.toString('utf8'); +console.log('转回字符串:', str); +// 验证是否一致 +if (str === chineseStr) { +console.log('✅ 转换一致!'); +} else { +console.log('❌ 转换不一致!'); +} + +路径处理:创建一个程序,接收文件路径,输出文件名、扩展名、所在目录。 +const path = require('path'); +// 获取命令行传入的文件路径 +const filePath = process.argv[2]; +if (!filePath) { +console.error('用法:node path-parse.js <文件路径>'); +console.error('示例:node path-parse.js /Users/xxx/project/src/index.js'); +process.exit(1); +} +// 解析路径信息 +const basename = path.basename(filePath); // 文件名(含扩展名) +const extname = path.extname(filePath); // 扩展名 +const dirname = path.dirname(filePath); // 所在目录 +const filename = path.basename(filePath, extname); // 文件名(不含扩展名) +// 输出结果 +console.log('=== 路径解析结果 ==='); +console.log('完整路径:', filePath); +console.log('文件名(含扩展名):', basename); +console.log('文件名(不含扩展名):', filename); +console.log('扩展名:', extname); +console.log('所在目录:', dirname); +//测试 +node path-parse.js /Users/xxx/project/src/index.js + +综合应用:创建一个CLI工具,接受命令行参数,实现简单的待办列表功能(添加、列出、删除)。 +const fs = require('fs'); +const path = require('path'); +// 待办数据文件路径 +const todoFile = path.join(\_\_dirname, 'todo.json'); +// 初始化待办文件(不存在则创建空数组) +function initTodoFile() { +if (!fs.existsSync(todoFile)) { +fs.writeFileSync(todoFile, JSON.stringify([], null, 2), 'utf8'); +} +} +// 读取待办列表 +function getTodos() { +initTodoFile(); +const data = fs.readFileSync(todoFile, 'utf8'); +return JSON.parse(data); +} +// 保存待办列表 +function saveTodos(todos) { +fs.writeFileSync(todoFile, JSON.stringify(todos, null, 2), 'utf8'); +} +// 处理命令 +const args = process.argv.slice(2); +const command = args[0]; +switch (command) { +// 添加待办 +case 'add': { +const content = args.slice(1).join(' '); +if (!content) { +console.error('用法:node todo.js add <待办内容>'); +process.exit(1); +} +const todos = getTodos(); +todos.push({ id: Date.now(), content, createTime: new Date().toLocaleString() }); +saveTodos(todos); +console.log(`✅ 已添加待办:${content}`); +break; +} +// 列出所有待办 +case 'list': { +const todos = getTodos(); +if (todos.length === 0) { +console.log('📄 暂无待办事项'); +break; +} +console.log('=== 待办列表 ==='); +todos.forEach((todo, index) => { +console.log(`${index + 1}. [${todo.id}] ${todo.content}(创建时间:${todo.createTime})`); +}); +break; +} +// 删除待办(按id) +case 'delete': { +const id = Number(args[1]); +if (isNaN(id)) { +console.error('用法:node todo.js delete <待办ID>'); +process.exit(1); +} +let todos = getTodos(); +const beforeLength = todos.length; +todos = todos.filter(todo => todo.id !== id); +if (todos.length === beforeLength) { +console.error('❌ 未找到该ID的待办'); +process.exit(1); +} +saveTodos(todos); +console.log(`✅ 已删除ID为${id}的待办`); +break; +} +// 帮助信息 +case 'help': +default: { +console.log('待办列表工具用法:'); +console.log(' node todo.js add <内容> - 添加待办'); +console.log(' node todo.js list - 列出所有待办'); +console.log(' node todo.js delete - 删除指定待办'); +console.log(' node todo.js help - 查看帮助'); +break; +} +} +//测试 +添加待办 +node todo.js add 学习Node.js内置模块 +列出待办 +node todo.js list +删除待办(替换ID为实际输出的ID) +node todo.js delete 1710888888888 diff --git "a/\345\206\257\344\273\201\351\224\220/20260318-\346\226\207\344\273\266\347\263\273\347\273\237.md" "b/\345\206\257\344\273\201\351\224\220/20260318-\346\226\207\344\273\266\347\263\273\347\273\237.md" new file mode 100644 index 00000000..2db29fb8 --- /dev/null +++ "b/\345\206\257\344\273\201\351\224\220/20260318-\346\226\207\344\273\266\347\263\273\347\273\237.md" @@ -0,0 +1,98 @@ +## 笔记 +const path = require('path'); + +// ━━ path.join() —— 智能拼接(相对路径,自动处理分隔符) +const relative = path.join(__dirname, '..', 'config', 'settings.json'); +// Linux: /project/config/settings.json +// Windows: C:\project\config\settings.json + +// ━━ path.resolve() —— 解析为绝对路径(从右往左,遇到绝对路径停止) +const absolute = path.resolve('src', 'index.js'); +// 以 process.cwd() 为基准解析为绝对路径 + +const absolute2 = path.resolve('/usr', 'local', 'bin'); +// /usr/local/bin(遇到 /usr 绝对路径,左侧忽略) + + +## 作业 +第一题 +// env-display.js +console.log('=== 当前系统环境变量 ===\n'); + +// 方式1:直接打印对象(可读性较差) +console.log(process.env); + +// 方式2:格式化输出(推荐) +Object.entries(process.env).sort().forEach(([key, value]) => { + console.log(`${key.padEnd(30)} = ${value}`); +}); + +// 方式3:筛选特定前缀(如 NODE_) +console.log('\n=== Node.js 相关变量 ==='); +Object.keys(process.env) + .filter(key => key.startsWith('NODE')) + .forEach(key => console.log(`${key}: ${process.env[key]}`)); +第二题 +// calculator.js +const path = require('path'); + +// 解析命令行参数(跳过 node 路径和脚本路径) +const args = process.argv.slice(2); + +// 使用说明 +if (args.length < 3 || args.includes('--help')) { + console.log(` + 用法: node calculator.js <操作> <数字1> <数字2> + + 操作: + add 加法 (a + b) + sub 减法 (a - b) + mul 乘法 (a * b) + div 除法 (a / b) + + 示例: + node calculator.js add 10 5 # 输出: 15 + node calculator.js mul 3.5 2 # 输出: 7 + `); + process.exit(0); +} + +const [command, numA, numB] = args; + +// 转换为数字并校验 +const a = parseFloat(numA); +const b = parseFloat(numB); + +if (isNaN(a) || isNaN(b)) { + console.error('错误:参数必须是有效数字'); + process.exit(1); +} + +// 运算逻辑 +let result; +switch (command) { + case 'add': + result = a + b; + console.log(`${a} + ${b} = ${result}`); + break; + case 'sub': + result = a - b; + console.log(`${a} - ${b} = ${result}`); + break; + case 'mul': + result = a * b; + console.log(`${a} × ${b} = ${result}`); + break; + case 'div': + if (b === 0) { + console.error('错误:除数不能为零'); + process.exit(1); + } + result = a / b; + console.log(`${a} ÷ ${b} = ${result}`); + break; + default: + console.error(`错误:未知操作 "${command}",支持: add/sub/mul/div`); + process.exit(1); +} + diff --git "a/\345\206\257\344\273\201\351\224\220/20260319-\346\226\207\344\273\266\347\263\273\347\273\237\346\250\241\345\235\227\347\273\203\344\271\240.md" "b/\345\206\257\344\273\201\351\224\220/20260319-\346\226\207\344\273\266\347\263\273\347\273\237\346\250\241\345\235\227\347\273\203\344\271\240.md" new file mode 100644 index 00000000..1f8bd7a7 --- /dev/null +++ "b/\345\206\257\344\273\201\351\224\220/20260319-\346\226\207\344\273\266\347\263\273\347\273\237\346\250\241\345\235\227\347\273\203\344\271\240.md" @@ -0,0 +1,68 @@ + + ## 练习 + ### 选择题 + - 下面哪个方法可以检查文件是否存在? + - B. fs.existsSync() + + - 写入文件使用哪个方法? + - B. fs.writeFileSync() + + - appendFileSync和writeFileSync的区别是? + - B. append是追加,write是覆盖 + + - 如何创建一个多级目录? + - B. fs.mkdirSync('./a/b/c', { recursive: true }) + + - 下面哪个方法可以获取文件的详细信息(大小、时间等)? + - C. fs.statSync() + + ### 简答题 + - 请解释同步方法和异步方法的区别。 + - 同步会阻塞后续操作,异步不会。 + + - fs.readFile和fs.readFileSync有什么区别? + - fs.readFile 是异步方法,‌不会阻塞‌主线程;fs.readFileSync 是同步方法,‌会阻塞‌整个 Node.js 进程直到文件读取完成。 + +- 什么是流式处理?它适合什么场景? + - 流式处理的优势在于能够实现低延迟响应、高效处理大规模实时数据流,并支持弹性伸缩。它特别适用于需要快速决策和响应变化的业务环境。 + +- 如何监听文件的变化? + - 可以使用 fs.watch 或 fs.watchFile 方法来监听文件或目录的变化。 + +```js +const fs = require('fs'); +const content = fs.readFileSync('./helin.txt', 'utf8'); +console.log(content); +fs.writeFileSync('./helin.txt', 'Hello World'); + + +const fs = require('fs/promises'); +const path = require('path'); + + function copyDirectory(src, dest) { + try { + + await fs.mkdir(dest, { recursive: true }); + + const entries = await fs.readdir(src, { withFileTypes: true }); + + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + + await copyDirectory(srcPath, destPath); + } else { + + await fs.copyFile(srcPath, destPath); + } + } + + console.log(`目录 "${src}" 已成功复制到 "${dest}"`); + } catch (err) { + console.error('复制目录时出错:', err.message); + } +} + ``` \ No newline at end of file diff --git "a/\345\206\257\344\273\201\351\224\220/20260320-HTML\346\250\241\346\235\277.md" "b/\345\206\257\344\273\201\351\224\220/20260320-HTML\346\250\241\346\235\277.md" new file mode 100644 index 00000000..83c979d4 --- /dev/null +++ "b/\345\206\257\344\273\201\351\224\220/20260320-HTML\346\250\241\346\235\277.md" @@ -0,0 +1,66 @@ +### 笔记 +``` +使用 http.request 发起 HTTP 请求 + +http.request 是一个通用方法,支持自定义 HTTP 方法(如 GET、POST、PUT 等)。以下是一个 POST 请求的示例: + +const http = require('http'); +const postData = JSON.stringify({ +title: 'Hello', +body: 'World', +userId: 1 +}); + +const options = { +hostname: 'jsonplaceholder.typicode.com', +port: 80, +path: '/posts', +method: 'POST', +headers: { +'Content-Type': 'application/json', +'Content-Length': Buffer.byteLength(postData) +} +}; + +const req = http.request(options, (res) => { +console.log(`状态码: ${res.statusCode}`); +console.log(`响应头: ${JSON.stringify(res.headers)}`); + +let data = ''; +res.on('data', (chunk) => { +data += chunk; +}); + +res.on('end', () => { +console.log(`响应数据: ${data}`); +}); +}); + +req.on('error', (e) => { +console.error(`请求出错: ${e.message}`); +}); + +// 发送请求数据 +req.write(postData); +req.end(); +``` +### 练习 +``` +1. 请解释req和res分别代表什么 +req:表示客户端的请求,只读 +res:表示服务器的响应,可写 + +2. http.createServer的回调函数接收哪些参数? +res req + +3. 如何获取URL中的查询参数? +使用req.url + +4. res.writeHead和res.setHeader有什么区别? +writeHead:一次性设置状态码和多个响应头,并发送响应头 +setHeader:单独设置单个响应头 + +5. http.get和http.request有什么区别? +get:仅支持GET请求,自动调用`req.end()` +request:支持所有HTTP方法,必须手动调用`req.end()` +``` \ No newline at end of file -- Gitee