From f927c25e5364d97d927d541718f5eeb1ae577b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=84=84=E6=88=90?= <425360154@qq.com> Date: Sun, 8 Mar 2026 00:11:04 +0800 Subject: [PATCH 1/2] 1 --- ...60306--\345\210\235\350\257\206Node.js.md" | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 "\344\275\225\345\204\204\346\210\220/20260306--\345\210\235\350\257\206Node.js.md" diff --git "a/\344\275\225\345\204\204\346\210\220/20260306--\345\210\235\350\257\206Node.js.md" "b/\344\275\225\345\204\204\346\210\220/20260306--\345\210\235\350\257\206Node.js.md" new file mode 100644 index 0000000..3a78f05 --- /dev/null +++ "b/\344\275\225\345\204\204\346\210\220/20260306--\345\210\235\350\257\206Node.js.md" @@ -0,0 +1,31 @@ +## 练习 +### 选择题 +1,Node.js是基于JavaScript的V8引擎开发的 +2,多线程不是Node.js的核心特性 +3,Node.js最适合开发实时聊天系统 +4, Ryan Dahl是Node.js的创始人 +5,Node.js中的"I/O"主要指Input/Output(输入/输出) + +### 简答题 +1,什么是Node.js? + - Node.js是一个基于ChromeV8引擎的JavaScript运行时环境,让JavaScript可以运行在服务器端(本地)。 +2,请解释"非阻塞I/O"是什么意思,它有什么优点? + - 一种高效的输入/输出(I/O)处理模型,事件驱动实现非阻塞I/O;优点:事件循环处理高并发 + +3,为什么Node.js适合开发实时聊天应用? + - 事件驱动 + 非阻塞 I/O 模型 + - WebSocket 原生友好 + 成熟生态(Socket.IO) + - 前后端统一语言(JavaScript) + +4,请列举Node.js的3个应用场景。 +- 实时聊天与协作应用 + - 利用 Node.js 的事件驱动和非阻塞 I/O 特性,结合 WebSocket(如 Socket.IO),可高效处理成千上万的并发连接,适用于在线聊天室、团队协作工具(如 Slack 后端)、实时通知系统等 。 + +- 高性能 API 与微服务开发 + - Node.js 轻量、启动快,非常适合构建 RESTful 或 GraphQL API 服务,为 Web 前端、移动端提供数据接口,也广泛用于微服务架构中作为独立的服务节点 。 + +- 前端工程化与构建工具 + - 基于 Node.js 的 npm 生态,催生了大量前端工具链,如 Webpack、Vite、Gulp 等,用于代码打包、压缩、转译、自动化测试等,已成为现代前端开发不可或缺的一部分 。 + +5,Node.js和传统后端语言(如Java、PHP)相比,有什么优势? + - 前后端统一语言(JavaScript \ No newline at end of file -- Gitee From ba53191a1d4f11aa68e259c55b9dc4cb8b973385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=84=84=E6=88=90?= <425360154@qq.com> Date: Sun, 15 Mar 2026 19:31:27 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E5=AD=A6=E4=B9=A0=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\347\256\241\347\220\206\345\231\250.md" | 211 +++++++++ ...77\347\224\250\346\250\241\345\235\227.md" | 215 +++++++++ ...31\345\205\245\346\226\207\344\273\266.md" | 102 ++++ .../20260313--\347\273\203\344\271\240.md" | 444 ++++++++++++++++++ 4 files changed, 972 insertions(+) create mode 100644 "\344\275\225\345\204\204\346\210\220/20260309--\345\214\205\347\256\241\347\220\206\345\231\250.md" create mode 100644 "\344\275\225\345\204\204\346\210\220/20260311--\344\275\277\347\224\250\346\250\241\345\235\227.md" create mode 100644 "\344\275\225\345\204\204\346\210\220/20260312--\345\244\204\347\220\206\345\221\275\344\273\244\350\241\214\345\206\231\345\205\245\346\226\207\344\273\266.md" create mode 100644 "\344\275\225\345\204\204\346\210\220/20260313--\347\273\203\344\271\240.md" diff --git "a/\344\275\225\345\204\204\346\210\220/20260309--\345\214\205\347\256\241\347\220\206\345\231\250.md" "b/\344\275\225\345\204\204\346\210\220/20260309--\345\214\205\347\256\241\347\220\206\345\231\250.md" new file mode 100644 index 0000000..df412c0 --- /dev/null +++ "b/\344\275\225\345\204\204\346\210\220/20260309--\345\214\205\347\256\241\347\220\206\345\231\250.md" @@ -0,0 +1,211 @@ +## 笔记 + +- 无DOM指无需操作网页;包管理器:管理第三方包(npm init -y安装依赖后,通过npm可以更新第三方包然后自动给express适配\[维护整个依赖网络。] ) +- 【SDK 通常是“别人写好的工具库”✅ SDK 只“声明”依赖,包管理器才“实现”依赖管理。;无论是 SDK 还是普通库,只要通过 npm/pip 安装,依赖管理就交给包管理器,而不是库本身。】 +- 环境变量\system32的某个,让net suer生效。 +- 标准json格式不允许key用单引号+注释+结尾;json5允许。 +- 部署项目前,打包项目会忽略开发环境时的工具(如,json里的Nodemon) + +## 练习 + +### 6.1 选择题 + +1. package.json中,哪个字段用于记录项目运行必需的依赖?B + - A. devDependencies + - B. dependencies + - C. scripts + - D. keywords +2. 版本号"^4.18.0"表示安装什么版本?B + - A. 只安装4.18.0 + - B. 安装4.x.x最新版本 + - C. 安装最新版本 + - D. 安装4.18.x最新版本 +3. 下面哪个命令可以查看npm的镜像源设置?B + - A. npm get registry + - B. npm config get registry + - C. npm view registry + - D. npm show registry +4. 安装全局包的参数是?C + - A. --save + - B. --save-dev + - C. --global + - D. -g +5. npm install 和 npm ci 有什么区别?B + - A. 没有区别 + - B. npm ci更快,适合CI/CD环境 + - C. npm ci更慢 + - D. npm ci会更新package.json +6. yarn相比npm有什么特点?B + - A. 速度更慢 + - B. 支持离线安装 + - C. 没有lock文件 + - D. 不支持Windows +7. pnpm的主要特点是什么?B + - A. 占用更多磁盘空间 + - B. 节省磁盘空间 + - C. 不支持并发安装 + - D. 必须联网才能使用 + +### 6.2 简答题 + +1. 请解释dependencies和devDependencies的区别。 + +- dependencies:项目在生产环境运行时必需的依赖,例如 React、Express、Axios。这些包会被打包进最终产物或部署到服务器。 +- devDependencies:仅在开发、构建、测试阶段需要的工具,例如nodemon、 Webpack、ESLint、Jest。它们不会被打包到生产环境,也不会被用户下载。 + +1. 什么是语义化版本号?请举例说明 "^1.2.3" 的含义。 + +版本号格式:`主版本.次版本.补丁版本` + +| 符号 | 含义 | 示例 | +| --- | ---- | ---------------------- | +| `^` | 兼容更新 | ^4.18.0 → 安装4.x.x最新版 | +| `~` | 补丁更新 | \~4.18.0 → 安装4.18.x最新版 | +| `*` | 最新版本 | \* → 安装最新版本 | +| 无符号 | 固定版本 | 4.18.0 → 只安装4.18.0 | + +```mermaid +flowchart TB + V[版本号 1.2.3] --> M[1 主版本\n不兼容的API变化] + V --> S[2 次版本\n向后兼容的新功能] + V --> P[3 补丁版本\n向后兼容的bug修复] +``` + +1. 为什么国内使用npm需要配置镜像源? + +- 显著提升下载速度,提高安装稳定性 + +1. 请描述npm install命令的执行过程。 + +- 读配置 → 解依赖 → 查缓存 → 下包 → 建 node\_modules → 写 lock 文件 → 跑脚本 + +1. 全局安装和本地安装有什么区别? + +| 对比项 | 全局安装(`-g`) | 本地安装(默认) | +| ------------------------- | ------------------------------------------ | --------------------------------------- | +| **安装位置** | 系统全局目录(如 `/usr/local/lib/node_modules`) | 项目 `./node_modules` | +| **用途** | CLI 工具(如 `create-react-app`, `typescript`) | 项目依赖(如 `express`, `lodash`) | +| **是否写入 package.json** | ❌ 否 | ✅ 是(`dependencies` 或 `devDependencies`) | +| **能否在代码中 require/import** | ❌ 不能 | ✅ 能 | +| **多项目隔离性** | ❌ 所有项目共享同一版本 | ✅ 每个项目可独立版本 | + +*** + +1. yarn和npm相比有什么优势? + +| 特性 | npm | yarn | pnpm | +| ------------- | ----------------- | --------- | -------------- | +| 安装速度 | 慢 | 快 | 最快 | +| 磁盘占用 | 大 | 中 | 小 | +| lock文件 | package-lock.json | yarn.lock | pnpm-lock.yaml | +| node\_modules | 扁平 | 扁平 | 平铺+符号链接 | +| 离线安装 | 不支持 | 支持 | 支持 | + +1. pnpm的node\_modules结构有什么特点?为什么能节省空间? + +- 所有包实际存储在 **全局 store**(如 `~/.pnpm/store`) +- `node_modules` 中只放指向 store 的链接 +- 多个项目共享同一份物理文件(通过硬链接) +- 避免了 npm/yarn 中“重复下载相同包”的问题 + +### 6.3 操作题 + +1. **创建项目**:使用npm init创建一个新项目,添加项目名称为"my-blog",作者为你的名字。 +2. **安装依赖**:安装express框架作为生产依赖,安装nodemon作为开发依赖。 +3. **查看信息**:使用npm view命令查看express的最新版本和所有版本。 +4. **配置脚本**:在package.json中添加一个"dev"脚本,使用nodemon运行index.js。 +5. **切换镜像**:将npm镜像切换为淘宝镜像,然后安装一个包验证速度。 +6. **安装yarn**:全局安装yarn,并使用yarn安装一个包体验速度。 +7. **安装pnpm**:全局安装pnpm,并使用pnpm安装一个包,观察node\_modules结构。 + +```bash +借助OWL框架复杂任务分成子agent后,自动化处理各种办公场景。 +我的观点是,OWL虽说是处理多智能体编排,但更主流/底层是处理一个大智能体,分成子智能体处理复杂任务# ============ 1. 创建项目 ============ +$ mkdir my-blog && cd my-blog +$ npm init -y +Wrote to /path/to/my-blog/package.json: +{ + "name": "my-blog", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "作者名", # ← 手动编辑 package.json 补充 author + "license": "ISC" +} + +# 手动修改 package.json 添加作者(因 npm init -y 不支持交互式填 author) +$ sed -i 's/"author": "",/"author": "作者名",/' package.json + +# ============ 2. 安装依赖 ============ +$ npm install express # 生产依赖 +added 48 packages, and audited 49 packages in 2s + +$ npm install -D nodemon # 开发依赖 +added 35 packages, and audited 84 packages in 1.8s + +# 验证 package.json 已更新 +$ cat package.json | grep -A5 -B5 "dependencies\|devDependencies" + "dependencies": { + "express": "^4.19.2" + }, + "devDependencies": { + "nodemon": "^3.1.4" + } + +# ============ 3. 查看 express 信息 ============ +$ npm view express version +4.19.2 + +$ npm view express versions --json | tail -5 + "4.18.2", + "4.18.3", + "4.19.0", + "4.19.1", + "4.19.2" +] + +# ============ 4. 配置 dev 脚本 ============ + +# 验证脚本 +$ npm run dev +[nodemon] 3.1.4 +[nodemon] to restart at any time, enter `rs` +[nodemon] watching path(s): *.* +[nodemon] starting `node index.js` +# (假设 index.js 不存在,会报错,但脚本已生效) + +# ============ 5. 切换淘宝镜像并验证 ============ +$ npm config set registry https://registry.npmmirror.com +$ npm config get registry +https://registry.npmmirror.com + +$ time npm install lodash +# 输出:added 1 package in 0.8s(比官方源快很多) + +# ============ 6. 安装 yarn 并体验 ============ +$ npm install -g yarn +added 1 package in 1.2s + +$ yarn add axios +# 输出:success Saved 1 new dependency. +# └─ axios@1.7.7 +# 速度明显快于 npm(尤其二次安装) + +# ============ 7. 安装 pnpm 并观察结构 ============ +$ npm install -g pnpm +added 1 package in 1.5s + +$ pnpm add dayjs +# 安装完成后查看 node_modules 结构 +$ ls -la node_modules/ +# 输出: +# drwxr-xr-x 3 user staff 96 Mar 9 17:30 .pnpm +# lrwxr-xr-x 1 user staff 38 Mar 9 17:30 dayjs -> .pnpm/dayjs@1.11.10/node_modules/dayjs + +# 可见 pnpm 使用符号链接,真实文件存于 .pnpm 目录,节省空间 +``` + diff --git "a/\344\275\225\345\204\204\346\210\220/20260311--\344\275\277\347\224\250\346\250\241\345\235\227.md" "b/\344\275\225\345\204\204\346\210\220/20260311--\344\275\277\347\224\250\346\250\241\345\235\227.md" new file mode 100644 index 0000000..9b8b145 --- /dev/null +++ "b/\344\275\225\345\204\204\346\210\220/20260311--\344\275\277\347\224\250\346\250\241\345\235\227.md" @@ -0,0 +1,215 @@ +## 笔记 +```bash +commonjs的暴露【导出模块到模块系统】,推荐的导出方式: +//方式2:导出对象(包含多个功能) +module.exports = { + add: function(a, b) { + return a + b; + }, + name: '张三', + PI: 3.14159 +}; +//引入方式: +let{add,substract}-require('./math.js'); +console.log(add(7,8)); +console.log(substract(7,8)) + + + +ES导出模块需要在package.json中设置“type”:“module”或者使用.js扩展名。: +// 方式1:命名导出(可导出多个) +export let name = '张三'; +export function add(a, b) { return a + b; } +export function subtract(a, b) { return a - b; } + +// 引入命名导出 +import { add, subtract } from './math.js'; +console.log(add(2, 3)); // 5 +``` + + +## 练习 +## 6 练习 + +### 6.1 选择题 + +1. 在CommonJS模块系统中,引入模块使用哪个关键字?B + - A. import + - B. require + - C. include + - D. load + +2. 以下哪个是正确的CommonJS导出方式?C + - A. export const add = ... + - B. exports = ... + - C. module.exports = ... + - D. export default ... + +3. ES Modules需要什么配置才能在Node.js中使用? B + - A. 设置 "type": "commonjs" + - B. 设置 "type": "module" + - C. 安装es-modules包 + - D. 无需任何配置 + +4. 下面的代码有什么问题?B + ```javascript + exports = function() { console.log('hello'); }; + ``` + - A. 没有问题 + - B. 应该是 module.exports + - C. 应该加括号 + - D. 应该是 export default + +5. 以下哪个不是模块化的好处?B + - A. 代码复用 + - B. 变量名冲突 + - C. 便于维护 + - D. 清晰结构 + +### 6.2 简答题 + +1. 什么是模块?为什么要使用模块? +- 一个.js就是模块。(一个Node.js就是一个模块,这个文件可能是js代码、JSON或者编译过的C\C++扩展); + +| 好处 | 说明 | +|------|------| +| **代码复用** | 写一次,处处使用 | +| **便于维护** | 修改一处,不影响全局 | +| **命名空间** | 避免变量名冲突 | +| **清晰结构** | 一眼看出项目组成 | +2. 请解释module.exports和exports的区别。 +- 都用于在 CommonJS 模块中导出内容。 +- 初始时:exports === module.exports(指向同一个对象)。 +- exports.foo/module.exports.foo = 'bar' ✅ 有效 修改的是 module.exports 对象的属性;exports = { foo: 'bar' } ❌ 无效 +3. CommonJS和ES Modules有什么区别? + +| 特性 | CommonJS | ES Modules | +|------|----------|------------| +| 引入方式 | `require()` | `import` | +| 导出方式 | `module.exports` | `export` | +| 加载方式 | 同步加载 | 异步加载 | +| 解析时机 | 运行时解析 | 编译时确定 | +| 使用场景 | Node.js服务端 | 前端/现代Node.js | +| 扩展名 | `.js` | `.js` 或配置 | + +4. Node.js加载模块的顺序是怎样的? +- .js → .json → .node(C++ 插件) + +5. 什么是模块作用域?它有什么作用? +- 每个 Node.js 文件(模块)拥有独立的作用域: + - math.js中const secret = 42; // 私有变量,外部,如add.js无法访问 + - math.js中module.exports 暴露add后,add.js可访问 + +### 6.3 操作题 + +1. **创建模块**:创建一个 `stringUtils.js` 模块,导出以下函数: + - `capitalize(str)` - 首字母大写 + - `reverse(str)` - 反转字符串 + - `trim(str)` - 去除两端空格 + +2. **使用模块**:创建 `index.js`,引入并测试 `stringUtils.js` 的所有函数。 + +3. **模块封装**:创建一个 `Person` 类,包含name、age属性和introduce方法,并在另一个文件中使用。 + +4. **模块加载实验**:创建一个有循环引用的模块对,观察Node.js如何处理。 + +5. **ES Modules尝试**(选做):将项目改为使用ES Modules,创建 `.js` 文件并测试import/export。 + +```bash +ES导出模块需要在package.json中设置“type”:“module”, +1、2: +// stringUtils.js +export function capitalize(str) { + if (typeof str !== 'string' || str.length === 0) return str; + return str.charAt(0).toUpperCase() + str.slice(1); +} + +export function reverse(str) { + if (typeof str !== 'string') return str; + return str.split('').reverse().join(''); +} + +export function trim(str) { + if (typeof str !== 'string') return str; + return str.trim(); +} + +// index.js +// --- 同步导入(命名导入)--- +import { capitalize, reverse, trim } from './stringUtils.js'; + +console.log('=== 同步导入测试 ==='); +console.log('capitalize("hello"):', capitalize('hello')); // Hello +console.log('reverse("world"):', reverse('world')); // dlrow +console.log('trim(" es modules "):', "{trim(' es modules ')}"); // "es modules" + +// --- 异步导入(动态加载)--- +console.log('n=== 异步导入测试 ==='); +const utils = await import('./stringUtils.js'); +console.log('utils.capitalize("async"):', utils.capitalize('async')); // Async +console.log('utils.reverse("load"):', utils.reverse('load')); // daol + +3, +// Person.js +export default class Person { + constructor(name, age) { + this.name = name; + this.age = age; + } + + introduce() { + return Hi, I'm {this.name}, ${this.age} years old.; + } +} + +// usePerson.js +// 默认导入 +import Person from './Person.js'; + +const alice = new Person('Alice', 25); +console.log('n=== Person 类测试 ==='); +console.log(alice.introduce()); // Hi, I'm Alice, 25 years old. + +// 异步导入默认导出 +const { default: PersonAsync } = await import('./Person.js'); +const bob = new PersonAsync('Bob', 30); +console.log(bob.introduce()); // Hi, I'm Bob, 30 years old. + +4 +// a.js +console.log('a.js 开始执行'); + +export const name = 'module-a'; + +export async function getBName() { + const b = await import('./b.js'); // 动态导入,避免静态循环依赖 + return b.name; +} + +console.log('a.js 执行完毕'); +// b.js +console.log('b.js 开始执行'); + +export const name = 'module-b'; + +export async function getAName() { + const a = await import('./a.js'); + return a.name; +} + +console.log('b.js 执行完毕'); +// testCycle.js +console.log('=== ESM 循环引用测试(动态导入)==='); +const a = await import('./a.js'); +const b = await import('./b.js'); + +console.log('a.getBName():', await a.getBName()); // 输出: module-b +console.log('b.getAName():', await b.getAName()); // 输出: module-a + +=== ESM 循环引用测试(动态导入)===node testCycle.js +a.js 开始执行 +a.js 执行完毕 +b.js 开始执行 +b.js 执行完毕 +a.getBName(): module-b +b.getAName(): module-a \ No newline at end of file diff --git "a/\344\275\225\345\204\204\346\210\220/20260312--\345\244\204\347\220\206\345\221\275\344\273\244\350\241\214\345\206\231\345\205\245\346\226\207\344\273\266.md" "b/\344\275\225\345\204\204\346\210\220/20260312--\345\244\204\347\220\206\345\221\275\344\273\244\350\241\214\345\206\231\345\205\245\346\226\207\344\273\266.md" new file mode 100644 index 0000000..949ed85 --- /dev/null +++ "b/\344\275\225\345\204\204\346\210\220/20260312--\345\244\204\347\220\206\345\221\275\344\273\244\350\241\214\345\206\231\345\205\245\346\226\207\344\273\266.md" @@ -0,0 +1,102 @@ +## 笔记 + +## 6 练习 + +### 6.1 选择题 + +1. Node.js中,获取命令行参数的属性是?B + + - A. process.args + - B. process.argv + - C. process.params + - D. process.args +2. 以下哪个命令可以读取文件内容?B + + - A. fs.writeFile + - B. fs.readFile + - C. fs.appendFile + - D. fs.copyFile +3. `__dirname` 表示什么?B + + - A. 当前文件的完整路径 + - B. 当前文件所在目录 + - C. 脚本运行时目录 + - D. Node.js安装目录 +4. package.json中,哪个字段用于配置全局命令?C + + - A. main + - B. scripts + - C. bin + - D. dependencies +5. 下面哪个不是命令行工具的优点?B + + - A. 自动化批量处理 + - B. 图形界面更美观 + - C. 部署便捷 + - D. 提高效率 + +### 6.2 简答题 + +1. 请解释什么是CLI工具?它和GUI有什么区别? + +- 用户在终端中输入命令,工具执行相应操作并返回文本结果。 +- 开发者、运维常用 CLI;普通用户更倾向 GUI(图形用户界面))。 + +2. process.argv返回的数组包含哪些内容? + 第 0 项:'node安装路径',(如 /usr/local/bin/node) + 第 1 项:当前执行的 JavaScript 文件的绝对路径 + 从第 2 项开始:用户传入的命令行参数 + +```bash +// 运行命令:node app.js one two three + +console.log(process.argv); + +// 输出: +// [ +// 'node安装路径', +// '脚本文件路径', +// 'one', +// 'two', +// 'three' +// ] +``` + +3. 请说明fs.readFileSync和fs.readFile的区别。 + +- fs.readFileSync:同步方法,会阻塞代码执行,直到文件读取完成。适合简单脚本或初始化配置。 +- fs.readFile:异步方法,使用回调函数或 Promise(配合 util.promisify 或 fs.promises),不会阻塞主线程,适合高并发或服务器环境。 + +4. 为什么要使用JSON文件存储数据?有什么优缺点? + +- 优点: + - 结构清晰,易于人类阅读和编写 + - 语言无关,几乎所有编程语言都支持解析 + - 与 JavaScript 无缝集成(JSON.parse() / JSON.stringify()) + - 适合存储配置、小型数据集、缓存等 +- 缺点: + - 不适合存储大量数据(无索引,查询效率低) + - 不支持并发写入(容易冲突) + - 无事务机制,写入中断可能导致文件损坏 + - 不能直接执行查询(不像数据库) + +5. 如何让开发的CLI工具可以全局使用? + +```bash +1,在 package.json 中配置 bin 字段,例如: +{ +"name": "my-cli", +"bin": { +"mycli": "./bin/cli.js" +} +} +2,在 ./bin/cli.js 文件顶部添加 Shebang: +#!/usr/bin/env node +console.log("Hello from CLI!"); +3,确保文件有可执行权限(Linux/macOS):chmod +x ./bin/cli.js +4,在项目根目录运行: +npm link # 本地全局链接(开发时) +# 或 +npm install -g . # 全局安装当前包 +之后就可以在终端任意位置运行 mycli 命令了。 +``` diff --git "a/\344\275\225\345\204\204\346\210\220/20260313--\347\273\203\344\271\240.md" "b/\344\275\225\345\204\204\346\210\220/20260313--\347\273\203\344\271\240.md" new file mode 100644 index 0000000..ca36ba5 --- /dev/null +++ "b/\344\275\225\345\204\204\346\210\220/20260313--\347\273\203\344\271\240.md" @@ -0,0 +1,444 @@ +## 笔记 + + +### 6.3 操作题 + +1. **完善待办工具**:完成本任务中的todo.js开发,并测试所有功能。 +2. **扩展功能**:为待办工具添加"优先级"功能,支持高/中/低优先级。 +3. **笔记工具**:开发一个简单的笔记CLI工具,支持: + + - `add <标题> <内容>` - 添加笔记 + - `list` - 列出所有笔记 + - `search <关键词>` - 搜索笔记 +4. **计算器工具**:开发一个命令行计算器,支持: + + - `add ` - 加法 + - `sub ` - 减法 + - `mul ` - 乘法 + - `div ` - 除法 +5. **文件处理工具**:开发一个文件处理工具,支持: + + - `count <文件名>` - 统计文件行数 + - `upper <文件名>` - 转为大写 + - `lower <文件名>` - 转为小写 + +```bash +第一题:todo.js: +//CLI参数 +import fs from 'fs'; +let a = process.argv[2]; +let b = process.argv[3]; +//模块处理,这里写入和写回方法 +function readDB(filePath = './todos.json') { + if (!fs.existsSync(filePath)) return []; + try { + return JSON.parse(fs.readFileSync(filePath, 'utf-8')) || []; + } + catch { + return [];// 兼容 JsON 损坏 + } + +} +function writeDB(fileContent, filePath = './todos.json') { + + //将json转成字符串再写入文件 + fs.writeFileSync(filePath, JSON.stringify(fileContent)); +} + +//CLI指令实现CRUD +if (a === 'add') { + if (!b) //“如果用户没提供任务序号 + { + console.log('用法: node todo.js add "任务内容"'); + process.exit(1); + } + let addArr = readDB(); + addArr.push({ 'title': b, 'isDone': false }); + writeDB(addArr); +} else if (a === 'del') { + let delArr = readDB(); + const index = parseInt(b) + + if (isNaN(index) || index < 1) { + console.log('❌ 请输入有效的任务序号(从1开始)'); + process.exit(1); + } + const realIndex = index - 1; + if (realIndex >= delArr.length) { + console.log('❌ 序号超出范围'); + process.exit(1); + } + delArr.splice(realIndex, 1);//上面用来校验 + writeDB(delArr); +} else if (a === 'done') { + + if (!b) { + console.log('用法: node todo.js done <序号>'); + process.exit(1); + } + const index = parseInt(b); + if (isNaN(index) || index < 1) { + console.log('❌ 请输入有效的任务序号(从1开始)'); + process.exit(1); + } + let doneArr = readDB(); + const realIndex = index - 1; + if (realIndex >= doneArr.length) { + console.log('❌ 序号超出范围'); + process.exit(1); + } + doneArr[realIndex].isDone = true; + writeDB(doneArr); + +} else if (a === 'clear') { + writeDB([]); // 清空为 空数组 +} + +else { + // 默认:列出所有任务 + const todos = readDB(); + if (todos.length === 0) { + console.log('📭 暂无任务\n用法: add / del / done / clear'); + } else { + console.log('📝 任务列表:'); + todos.forEach((todo, i) => { + const mark = todo.isDone ? '✅' : '⬜'; + console.log(`${i + 1}. ${mark} ${todo.title}`); + }); + } // 👈 补上这个!闭合内层 else +} // 👈 闭合最外层 else + +``` + +```bash +第二题: +// CLI参数 +import fs from 'fs'; +let cmd = process.argv[2]; +let arg1 = process.argv[3]; +let arg2 = process.argv[4]; // 新增:优先级参数(可选) + +function read(filePath = './todos.json') { + try { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); + } catch { + return []; + } +} + +function write(fileContent, filePath = './todos.json') { + fs.writeFileSync(filePath, JSON.stringify(fileContent)); +} + +// 优先级映射 +const prioMap = { H: '🔴', M: '🟡', L: '🟢' }; + +if (cmd === 'add') { + if (!arg1) { + console.log('用法: node todo.js add "任务" [H|M|L]'); + process.exit(1); + } + const prio = arg2 && ['H','M','L'].includes(arg2) ? arg2 : 'M'; // 默认 M + const todos = read(); + todos.push({ title: arg1, isDone: false, priority: prio }); + write(todos); + console.log(`✅ 已添加: ${arg1} (${prio})`); + +} else if (cmd === 'del' || cmd === 'done') { + const todos = read(); + const i = parseInt(arg1) - 1; + if (todos[i]) { + if (cmd === 'done') { + todos[i].isDone = true; + } else { + todos.splice(i, 1); + } + write(todos); + } + +} else if (cmd === 'clear') { + write([]); + +} else { + // list + const todos = read(); + if (todos.length === 0) { + console.log('📭 没任务'); + console.log('\n用法: add "任务" [H|M|L] | done 1 | del 1 | clear'); + } else { + todos.forEach((t, i) => { + const mark = t.isDone ? '✅' : '⬜'; + const prioIcon = prioMap[t.priority] || '🟡'; + console.log(`${i + 1}. ${prioIcon} ${mark} ${t.title}`); + }); + } +} + +# 添加不同优先级任务 +node todo.js add "修复 bug" H # 高 +node todo.js add "写文档" M # 中(默认) +node todo.js add "整理桌面" L # 低 + +# 查看(自动带图标) +node todo.js +# 输出: +# 1. 🔴 ⬜ 修复 bug +# 2. 🟡 ⬜ 写文档 +# 3. 🟢 ⬜ 整理桌面 + +# 其他命令不变 +node todo.js done 1 +node todo.js del 3 +node todo.js clear + + +数据文件 todos.json 示例 +[ + {"title":"修复 bug","isDone":false,"priority":"H"}, + {"title":"写文档","isDone":true,"priority":"M"}, + {"title":"整理桌面","isDone":false,"priority":"L"} +] +``` + +```bash +第三题 +// CLI参数 +import fs from 'fs'; +let cmd = process.argv[2]; +let arg1 = process.argv[3]; +let arg2 = process.argv[4]; + +// 读写方法 +function readDB(filePath = './notes.json') { + if (!fs.existsSync(filePath)) return []; + try { + return JSON.parse(fs.readFileSync(filePath, 'utf8')) || []; + } catch { + return []; // 兼容 JSON 损坏 + } +} + +function writeDB(data, filePath = './notes.json') { + fs.writeFileSync(filePath, JSON.stringify(data)); +} + +// 命令处理 +if (cmd === 'add') { + if (!arg1 || !arg2) { + console.log('用法: node note.js add "<标题>" "<内容>"'); + process.exit(1); + } + const notes = readDB(); + notes.push({ title: arg1, content: arg2 }); + writeDB(notes); + console.log(`✅ 已添加笔记: ${arg1}`); + +} else if (cmd === 'list') { + const notes = readDB(); + if (notes.length === 0) { + console.log('📭 暂无笔记'); + } else { + console.log('📝 所有笔记:'); + notes.forEach((note, i) => { + console.log(`${i + 1}. ${note.title}`); + console.log(` ${note.content}\n`); + }); + } + +} else if (cmd === 'search') { + if (!arg1) { + console.log('用法: node note.js search <关键词>'); + process.exit(1); + } + const notes = readDB(); + const results = notes.filter(note => + note.title.includes(arg1) || note.content.includes(arg1) + ); + if (results.length === 0) { + console.log(`🔍 未找到包含 "${arg1}" 的笔记`); + } else { + console.log(`🔍 搜索结果(共 ${results.length} 条):`); + results.forEach((note, i) => { + console.log(`${i + 1}. ${note.title}`); + console.log(` ${note.content}\n`); + }); + } + +} else { + console.log('📌 笔记工具'); + console.log('用法:'); + console.log(' node note.js add "<标题>" "<内容>"'); + console.log(' node note.js list'); + console.log(' node note.js search <关键词>'); +} + 使用示例: + // CLI参数 +import fs from 'fs'; +let cmd = process.argv[2]; +let arg1 = process.argv[3]; +let arg2 = process.argv[4]; + +// 读写方法 +function readDB(filePath = './notes.json') { + if (!fs.existsSync(filePath)) return []; + try { + return JSON.parse(fs.readFileSync(filePath, 'utf8')) || []; + } catch { + return []; // 兼容 JSON 损坏 + } +} + +function writeDB(data, filePath = './notes.json') { + fs.writeFileSync(filePath, JSON.stringify(data)); +} + +// 命令处理 +if (cmd === 'add') { + if (!arg1 || !arg2) { + console.log('用法: node note.js add "<标题>" "<内容>"'); + process.exit(1); + } + const notes = readDB(); + notes.push({ title: arg1, content: arg2 }); + writeDB(notes); + console.log(`✅ 已添加笔记: ${arg1}`); + +} else if (cmd === 'list') { + const notes = readDB(); + if (notes.length === 0) { + console.log('📭 暂无笔记'); + } else { + console.log('📝 所有笔记:'); + notes.forEach((note, i) => { + console.log(`${i + 1}. ${note.title}`); + console.log(` ${note.content}\n`); + }); + } + +} else if (cmd === 'search') { + if (!arg1) { + console.log('用法: node note.js search <关键词>'); + process.exit(1); + } + const notes = readDB(); + const results = notes.filter(note => + note.title.includes(arg1) || note.content.includes(arg1) + ); + if (results.length === 0) { + console.log(`🔍 未找到包含 "${arg1}" 的笔记`); + } else { + console.log(`🔍 搜索结果(共 ${results.length} 条):`); + results.forEach((note, i) => { + console.log(`${i + 1}. ${note.title}`); + console.log(` ${note.content}\n`); + }); + } + +} else { + console.log('📌 笔记工具'); + console.log('用法:'); + console.log(' node note.js add "<标题>" "<内容>"'); + console.log(' node note.js list'); + console.log(' node note.js search <关键词>'); +} +``` + +```bash +第四题 +// CLI参数 +let cmd = process.argv[2]; +let a = parseFloat(process.argv[3]); +let b = parseFloat(process.argv[4]); + +if (!cmd || isNaN(a) || isNaN(b)) { + console.log('用法:'); + console.log(' node calc.js add '); + console.log(' node calc.js sub '); + console.log(' node calc.js mul '); + console.log(' node calc.js div '); + process.exit(1); +} + + +let result; +switch (cmd) { + case 'add': result = a + b; break; + case 'sub': result = a - b; break; + case 'mul': result = a * b; break; + case 'div': + if (b === 0) { + console.log('❌ 除数不能为0'); + process.exit(1); + } + result = a / b; + break; + default: + console.log('❌ 不支持的命令:', cmd); + process.exit(1); +} + +console.log(result); +使用示例 +node calc.js add 3 5 # 输出: 8 +node calc.js div 10 3 # 输出: 3.3333333333333335 +node calc.js div 5 0 # 报错: 除数不能为0 +``` + +```bash +第五题 +import fs from 'fs'; + +let cmd = process.argv[2]; +let filename = process.argv[3]; + +if (!cmd || !filename) { + console.log('用法:'); + console.log(' node filetool.js count <文件名> # 统计行数'); + console.log(' node filetool.js upper <文件名> # 转大写'); + console.log(' node filetool.js lower <文件名> # 转小写'); + process.exit(1); +} +try { + if (cmd === 'count') { + const content = fs.readFileSync(filename, 'utf8'); + const lines = content.split(/\r?\n/).filter(line => line.trim() !== '').length; + console.log(`📄 ${filename} 共 ${lines} 行(非空)`); + + } else if (cmd === 'upper') { + const content = fs.readFileSync(filename, 'utf8'); + console.log(content.toUpperCase()); + + } else if (cmd === 'lower') { + const content = fs.readFileSync(filename, 'utf8'); + console.log(content.toLowerCase()); + + } else { + console.log('❌ 不支持的命令:', cmd); + process.exit(1); + } + +} catch (err) { + console.log('❌ 文件错误:', err.message); + process.exit(1); +} +使用示例 +假设有一个 test.txt 内容为: +Hello World +Node.js is Fun! +则 +# 统计行数 +node filetool.js count test.txt +# 输出: 📄 test.txt 共 2 行(非空) + +# 转大写(输出到终端) +node filetool.js upper test.txt +# 输出: +# HELLO WORLD +# NODE.JS IS FUN! + +# 转小写 +node filetool.js lower test.txt +# 输出: +# hello world +# node.js is fun! +``` -- Gitee