@lppx/nlearn 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. package/dist/scripts/sync-repo.js +100 -0
  2. package/dist/src/cli/cli.js +9 -0
  3. package/dist/src/demo/commander/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +174 -0
  4. package/dist/src/demo/commander/02-/345/221/275/344/273/244/347/263/273/347/273/237.js +260 -0
  5. package/dist/src/demo/commander/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +285 -0
  6. package/dist/src/demo/commander/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +408 -0
  7. package/dist/src/demo/esm/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +226 -0
  8. package/dist/src/demo/esm/02-/345/257/274/345/207/272/350/257/255/346/263/225.js +281 -0
  9. package/dist/src/demo/esm/03-/345/257/274/345/205/245/350/257/255/346/263/225.js +366 -0
  10. package/dist/src/demo/esm/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +509 -0
  11. package/dist/src/demo/inquirer/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +135 -0
  12. package/dist/src/demo/inquirer/02-/351/200/211/346/213/251/347/261/273/345/236/213.js +143 -0
  13. package/dist/src/demo/inquirer/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +211 -0
  14. package/dist/src/demo/inquirer/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +343 -0
  15. package/dist/src/demo/yargs/01-/345/237/272/347/241/200/346/246/202/345/277/265.js +142 -0
  16. package/dist/src/demo/yargs/02-/345/221/275/344/273/244/347/263/273/347/273/237.js +211 -0
  17. package/dist/src/demo/yargs/03-/351/253/230/347/272/247/347/211/271/346/200/247.js +205 -0
  18. package/dist/src/demo/yargs/04-/345/256/236/346/210/230/346/241/210/344/276/213.js +276 -0
  19. package/package.json +39 -0
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ /**
3
+ * ESM 基础概念
4
+ * ============
5
+ * 本文件介绍 ECMAScript Modules (ESM) 的基本概念和语法
6
+ * 适用于 Node.js 14+ 版本
7
+ *
8
+ * ESM vs CommonJS:
9
+ * - ESM 是 JavaScript 的官方标准模块系统
10
+ * - CommonJS 是 Node.js 早期采用的模块系统
11
+ * - ESM 使用 import/export,CommonJS 使用 require/module.exports
12
+ */
13
+ // #region 示例1: 什么是模块系统
14
+ /**
15
+ * 模块系统的作用:
16
+ * 1. 代码组织:将代码分割成独立的文件
17
+ * 2. 作用域隔离:每个模块有自己的作用域
18
+ * 3. 依赖管理:明确模块之间的依赖关系
19
+ * 4. 代码复用:方便在不同地方使用相同的代码
20
+ */
21
+ function explainModuleSystem() {
22
+ console.log(`=== 模块系统的核心概念 ===
23
+
24
+ 1. 模块(Module):
25
+ - 一个文件就是一个模块
26
+ - 每个模块有独立的作用域
27
+ - 模块内的变量默认是私有的
28
+
29
+ 2. 导出(Export):
30
+ - 将模块内的功能暴露给外部使用
31
+ - 可以导出变量、函数、类等
32
+
33
+ 3. 导入(Import):
34
+ - 从其他模块引入需要的功能
35
+ - 只能使用被导出的内容
36
+ `);
37
+ }
38
+ // #endregion
39
+ // #region 示例2: ESM 与 CommonJS 的对比
40
+ function compareModuleSystems() {
41
+ console.log(`=== ESM vs CommonJS 对比 ===
42
+
43
+ 【语法对比】
44
+ CommonJS 导出:
45
+ module.exports = { ... }
46
+ exports.name = value
47
+
48
+ ESM 导出:
49
+ export { ... }
50
+ export default ...
51
+
52
+ CommonJS 导入:
53
+ const module = require("./module")
54
+ const { name } = require("./module")
55
+
56
+ ESM 导入:
57
+ import module from "./module.js"
58
+ import { name } from "./module.js"
59
+
60
+ 【关键差异】
61
+ 1. 加载时机:
62
+ - CommonJS: 运行时同步加载
63
+ - ESM: 编译时静态分析,异步加载
64
+
65
+ 2. 文件扩展名:
66
+ - CommonJS: 可省略 .js
67
+ - ESM: 必须包含完整扩展名 .js 或 .mjs
68
+
69
+ 3. this 指向:
70
+ - CommonJS: this 指向 module.exports
71
+ - ESM: this 是 undefined
72
+
73
+ 4. 循环依赖:
74
+ - CommonJS: 返回未完成的副本
75
+ - ESM: 支持更好的循环依赖处理
76
+ `);
77
+ }
78
+ // #endregion
79
+ // #region 示例3: 如何在 Node.js 中启用 ESM
80
+ function enableESMInNodejs() {
81
+ console.log(`=== 在 Node.js 中启用 ESM ===
82
+
83
+ 方法1: 使用 .mjs 扩展名
84
+ - 将文件命名为 .mjs
85
+ - Node.js 会自动将其视为 ESM 模块
86
+ - 示例: module.mjs
87
+
88
+ 方法2: 在 package.json 中设置 type
89
+ {
90
+ "type": "module"
91
+ }
92
+ - 所有 .js 文件都会被视为 ESM
93
+ - 如需使用 CommonJS,文件需命名为 .cjs
94
+
95
+ 方法3: 使用 TypeScript
96
+ - 在 tsconfig.json 中设置:
97
+ "module": "ES2020" 或 "ESNext"
98
+ - TypeScript 会编译为 ESM 格式
99
+
100
+ 注意事项:
101
+ - ESM 和 CommonJS 可以互操作,但有限制
102
+ - ESM 可以导入 CommonJS 模块
103
+ - CommonJS 不能直接 require ESM 模块
104
+ `);
105
+ }
106
+ // #endregion
107
+ // #region 示例4: ESM 的严格模式
108
+ function esmStrictMode() {
109
+ console.log(`=== ESM 的严格模式 ===
110
+
111
+ ESM 模块自动运行在严格模式下:
112
+ 1. 不需要显式声明 "use strict"
113
+ 2. 禁止使用未声明的变量
114
+ 3. 禁止删除变量、函数
115
+ 4. 函数参数名不能重复
116
+ 5. 禁止八进制字面量
117
+
118
+ 示例:
119
+ // 在 ESM 中,以下代码会报错:
120
+ // x = 10; // ReferenceError: x is not defined
121
+
122
+ // 必须先声明:
123
+ // let x = 10; // 正确
124
+ `);
125
+ }
126
+ // #endregion
127
+ // #region 示例5: 模块作用域
128
+ function moduleScope() {
129
+ // 模块内的变量
130
+ const privateVar = '这是私有变量';
131
+ const publicVar = '这是公开变量';
132
+ console.log(`=== 模块作用域 ===
133
+
134
+ 每个模块都有独立的作用域:
135
+
136
+ 1. 私有变量:
137
+ ${privateVar}
138
+ - 未导出的变量只能在模块内部访问
139
+ - 外部无法访问
140
+
141
+ 2. 公开变量:
142
+ ${publicVar}
143
+ - 通过 export 导出后,外部可以导入使用
144
+ - 但仍然是只读的(不能重新赋值)
145
+
146
+ 3. 全局对象:
147
+ - 在 ESM 中,顶层的 this 是 undefined
148
+ - 不会污染全局作用域
149
+ - 使用 globalThis 访问全局对象
150
+ `);
151
+ }
152
+ // #endregion
153
+ // 主函数:根据参数运行指定示例
154
+ if (require.main === module) {
155
+ const args = process.argv.slice(2);
156
+ const exampleNum = args[0] ? parseInt(args[0]) : 0;
157
+ if (exampleNum === 0) {
158
+ // 运行所有示例
159
+ console.log(`
160
+ ${'='.repeat(50)}
161
+ 运行所有示例
162
+ ${'='.repeat(50)}
163
+ `);
164
+ explainModuleSystem();
165
+ console.log('\n' + '-'.repeat(50) + '\n');
166
+ compareModuleSystems();
167
+ console.log('\n' + '-'.repeat(50) + '\n');
168
+ enableESMInNodejs();
169
+ console.log('\n' + '-'.repeat(50) + '\n');
170
+ esmStrictMode();
171
+ console.log('\n' + '-'.repeat(50) + '\n');
172
+ moduleScope();
173
+ console.log('\n' + '='.repeat(50));
174
+ }
175
+ else if (exampleNum === 1) {
176
+ console.log(`
177
+ 运行示例 1: 什么是模块系统
178
+
179
+ ${'='.repeat(50)}`);
180
+ explainModuleSystem();
181
+ console.log('='.repeat(50));
182
+ }
183
+ else if (exampleNum === 2) {
184
+ console.log(`
185
+ 运行示例 2: ESM 与 CommonJS 的对比
186
+
187
+ ${'='.repeat(50)}`);
188
+ compareModuleSystems();
189
+ console.log('='.repeat(50));
190
+ }
191
+ else if (exampleNum === 3) {
192
+ console.log(`
193
+ 运行示例 3: 如何在 Node.js 中启用 ESM
194
+
195
+ ${'='.repeat(50)}`);
196
+ enableESMInNodejs();
197
+ console.log('='.repeat(50));
198
+ }
199
+ else if (exampleNum === 4) {
200
+ console.log(`
201
+ 运行示例 4: ESM 的严格模式
202
+
203
+ ${'='.repeat(50)}`);
204
+ esmStrictMode();
205
+ console.log('='.repeat(50));
206
+ }
207
+ else if (exampleNum === 5) {
208
+ console.log(`
209
+ 运行示例 5: 模块作用域
210
+
211
+ ${'='.repeat(50)}`);
212
+ moduleScope();
213
+ console.log('='.repeat(50));
214
+ }
215
+ else {
216
+ console.log(`可用的示例:
217
+ 1. 什么是模块系统
218
+ 2. ESM 与 CommonJS 的对比
219
+ 3. 如何在 Node.js 中启用 ESM
220
+ 4. ESM 的严格模式
221
+ 5. 模块作用域
222
+
223
+ 使用方法: ts-node 01-基础概念.ts [示例编号]
224
+ 不提供编号则运行所有示例`);
225
+ }
226
+ }
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ /**
3
+ * ESM 导出语法
4
+ * ============
5
+ * 本文件详细介绍 ESM 的各种导出方式
6
+ * 包括命名导出、默认导出、重导出等
7
+ */
8
+ // #region 示例1: 命名导出(Named Exports)
9
+ /**
10
+ * 命名导出:可以导出多个值,每个值都有自己的名称
11
+ * 导入时必须使用相同的名称(或使用 as 重命名)
12
+ */
13
+ function demonstrateNamedExports() {
14
+ console.log(`=== 命名导出 ===
15
+
16
+ 语法形式1: 声明时导出
17
+ export const name = "value";
18
+ export function func() {}
19
+ export class MyClass {}
20
+
21
+ 语法形式2: 声明后导出
22
+ const name = "value";
23
+ function func() {}
24
+ export { name, func };
25
+
26
+ 语法形式3: 导出时重命名
27
+ const internalName = "value";
28
+ export { internalName as publicName };
29
+
30
+ 示例代码:
31
+ ---
32
+ // math.js
33
+ export const PI = 3.14159;
34
+ export function add(a, b) { return a + b; }
35
+ export function multiply(a, b) { return a * b; }
36
+ ---
37
+
38
+ 特点:
39
+ ✓ 可以导出多个值
40
+ ✓ 导入时使用花括号 {}
41
+ ✓ 名称必须匹配(或使用 as 重命名)
42
+ ✓ 支持 Tree Shaking(未使用的导出会被移除)
43
+ `);
44
+ }
45
+ // #endregion
46
+ // #region 示例2: 默认导出(Default Export)
47
+ /**
48
+ * 默认导出:每个模块只能有一个默认导出
49
+ * 导入时可以使用任意名称
50
+ */
51
+ function demonstrateDefaultExport() {
52
+ console.log(`=== 默认导出 ===
53
+
54
+ 语法形式1: 导出值
55
+ export default 42;
56
+ export default "hello";
57
+
58
+ 语法形式2: 导出函数
59
+ export default function() {}
60
+ export default function myFunc() {}
61
+
62
+ 语法形式3: 导出类
63
+ export default class {}
64
+ export default class MyClass {}
65
+
66
+ 语法形式4: 导出已声明的值
67
+ const value = 42;
68
+ export default value;
69
+
70
+ 示例代码:
71
+ ---
72
+ // calculator.js
73
+ export default class Calculator {
74
+ add(a, b) { return a + b; }
75
+ subtract(a, b) { return a - b; }
76
+ }
77
+ ---
78
+
79
+ 特点:
80
+ ✓ 每个模块只能有一个默认导出
81
+ ✓ 导入时不使用花括号
82
+ ✓ 导入时可以使用任意名称
83
+ ✓ 适合导出模块的主要功能
84
+ `);
85
+ }
86
+ // #endregion
87
+ // #region 示例3: 混合导出
88
+ /**
89
+ * 混合导出:同时使用命名导出和默认导出
90
+ */
91
+ function demonstrateMixedExports() {
92
+ console.log('=== 混合导出 ===\n');
93
+ console.log('可以在同一个模块中同时使用命名导出和默认导出:\n');
94
+ console.log('示例代码:');
95
+ console.log('---');
96
+ console.log('// utils.js');
97
+ console.log('export const VERSION = "1.0.0";');
98
+ console.log('export function helper() {}');
99
+ console.log('');
100
+ console.log('export default class MainClass {');
101
+ console.log(' // 主要功能');
102
+ console.log('}');
103
+ console.log('---\n');
104
+ console.log('导入方式:');
105
+ console.log(' import MainClass, { VERSION, helper } from "./utils.js";\n');
106
+ console.log('使用场景:');
107
+ console.log(' - 模块有一个主要功能(默认导出)');
108
+ console.log(' - 同时提供一些辅助功能(命名导出)');
109
+ console.log(' - 例如:React 组件(默认)+ 工具函数(命名)\n');
110
+ }
111
+ // #endregion
112
+ // #region 示例4: 重导出(Re-exports)
113
+ /**
114
+ * 重导出:从其他模块导入后再导出
115
+ * 常用于创建统一的入口文件
116
+ */
117
+ function demonstrateReExports() {
118
+ console.log('=== 重导出 ===\n');
119
+ console.log('语法形式1: 重导出所有命名导出');
120
+ console.log(' export * from "./module.js";\n');
121
+ console.log('语法形式2: 重导出特定的命名导出');
122
+ console.log(' export { name1, name2 } from "./module.js";\n');
123
+ console.log('语法形式3: 重导出并重命名');
124
+ console.log(' export { oldName as newName } from "./module.js";\n');
125
+ console.log('语法形式4: 重导出默认导出为命名导出');
126
+ console.log(' export { default as myName } from "./module.js";\n');
127
+ console.log('语法形式5: 重导出命名导出为默认导出');
128
+ console.log(' export { myName as default } from "./module.js";\n');
129
+ console.log('实际应用示例:');
130
+ console.log('---');
131
+ console.log('// components/index.js (统一入口)');
132
+ console.log('export { Button } from "./Button.js";');
133
+ console.log('export { Input } from "./Input.js";');
134
+ console.log('export { Modal } from "./Modal.js";');
135
+ console.log('');
136
+ console.log('// 使用时只需从一个文件导入');
137
+ console.log('import { Button, Input, Modal } from "./components/index.js";');
138
+ console.log('---\n');
139
+ console.log('注意事项:');
140
+ console.log(' - export * 不会重导出默认导出');
141
+ console.log(' - 重导出时不能在当前模块中使用这些值');
142
+ console.log(' - 适合创建 barrel 文件(桶文件)\n');
143
+ }
144
+ // #endregion
145
+ // #region 示例5: 聚合导出模式
146
+ /**
147
+ * 聚合导出:将多个模块的导出聚合到一个文件
148
+ */
149
+ function demonstrateAggregateExports() {
150
+ console.log('=== 聚合导出模式 ===\n');
151
+ console.log('场景:有多个相关的模块,想要提供统一的导入入口\n');
152
+ console.log('文件结构:');
153
+ console.log(' utils/');
154
+ console.log(' ├── string.js');
155
+ console.log(' ├── array.js');
156
+ console.log(' ├── object.js');
157
+ console.log(' └── index.js (聚合文件)\n');
158
+ console.log('各模块内容:');
159
+ console.log('---');
160
+ console.log('// string.js');
161
+ console.log('export function capitalize(str) { ... }');
162
+ console.log('export function trim(str) { ... }');
163
+ console.log('');
164
+ console.log('// array.js');
165
+ console.log('export function unique(arr) { ... }');
166
+ console.log('export function flatten(arr) { ... }');
167
+ console.log('');
168
+ console.log('// object.js');
169
+ console.log('export function merge(obj1, obj2) { ... }');
170
+ console.log('export function clone(obj) { ... }');
171
+ console.log('---\n');
172
+ console.log('聚合文件 (index.js):');
173
+ console.log('---');
174
+ console.log('// 方式1: 分别重导出');
175
+ console.log('export * from "./string.js";');
176
+ console.log('export * from "./array.js";');
177
+ console.log('export * from "./object.js";');
178
+ console.log('');
179
+ console.log('// 方式2: 按命名空间组织');
180
+ console.log('export * as StringUtils from "./string.js";');
181
+ console.log('export * as ArrayUtils from "./array.js";');
182
+ console.log('export * as ObjectUtils from "./object.js";');
183
+ console.log('---\n');
184
+ console.log('使用方式:');
185
+ console.log('// 方式1: 直接导入所有函数');
186
+ console.log('import { capitalize, unique, merge } from "./utils/index.js";');
187
+ console.log('');
188
+ console.log('// 方式2: 按命名空间导入');
189
+ console.log('import { StringUtils, ArrayUtils } from "./utils/index.js";');
190
+ console.log('StringUtils.capitalize("hello");\n');
191
+ }
192
+ // #endregion
193
+ // #region 示例6: 导出的注意事项
194
+ function exportCaveats() {
195
+ console.log('=== 导出的注意事项 ===\n');
196
+ console.log('1. 导出的是绑定,不是值的副本:');
197
+ console.log('---');
198
+ console.log('// counter.js');
199
+ console.log('export let count = 0;');
200
+ console.log('export function increment() { count++; }');
201
+ console.log('');
202
+ console.log('// main.js');
203
+ console.log('import { count, increment } from "./counter.js";');
204
+ console.log('console.log(count); // 0');
205
+ console.log('increment();');
206
+ console.log('console.log(count); // 1 (值会更新)');
207
+ console.log('---\n');
208
+ console.log('2. 导入的绑定是只读的:');
209
+ console.log('---');
210
+ console.log('import { count } from "./counter.js";');
211
+ console.log('count = 10; // TypeError: Assignment to constant variable');
212
+ console.log('---\n');
213
+ console.log('3. 导出语句必须在顶层:');
214
+ console.log('---');
215
+ console.log('// ❌ 错误:不能在条件语句中导出');
216
+ console.log('if (condition) {');
217
+ console.log(' export const value = 42; // SyntaxError');
218
+ console.log('}');
219
+ console.log('');
220
+ console.log('// ✓ 正确:在顶层导出');
221
+ console.log('export const value = condition ? 42 : 0;');
222
+ console.log('---\n');
223
+ console.log('4. 不能导出未声明的变量:');
224
+ console.log('---');
225
+ console.log('// ❌ 错误');
226
+ console.log('export { undeclaredVar }; // ReferenceError');
227
+ console.log('');
228
+ console.log('// ✓ 正确');
229
+ console.log('const declaredVar = 42;');
230
+ console.log('export { declaredVar };');
231
+ console.log('---\n');
232
+ }
233
+ // #endregion
234
+ function runAllExportExamples() {
235
+ console.log(`
236
+ ${'='.repeat(50)}
237
+ 运行所有示例
238
+ ${'='.repeat(50)}
239
+ `);
240
+ demonstrateNamedExports();
241
+ console.log('\n' + '-'.repeat(50) + '\n');
242
+ demonstrateDefaultExport();
243
+ console.log('\n' + '-'.repeat(50) + '\n');
244
+ demonstrateMixedExports();
245
+ console.log('\n' + '-'.repeat(50) + '\n');
246
+ demonstrateReExports();
247
+ console.log('\n' + '-'.repeat(50) + '\n');
248
+ demonstrateAggregateExports();
249
+ console.log('\n' + '-'.repeat(50) + '\n');
250
+ exportCaveats();
251
+ console.log('\n' + '='.repeat(50));
252
+ }
253
+ // 主函数:根据参数运行指定示例
254
+ if (require.main === module) {
255
+ const args = process.argv.slice(2);
256
+ const exampleNum = args[0] ? parseInt(args[0]) : 0;
257
+ const examples = [
258
+ { name: '所有示例', fn: runAllExportExamples },
259
+ { name: '命名导出', fn: demonstrateNamedExports },
260
+ { name: '默认导出', fn: demonstrateDefaultExport },
261
+ { name: '混合导出', fn: demonstrateMixedExports },
262
+ { name: '重导出', fn: demonstrateReExports },
263
+ { name: '聚合导出模式', fn: demonstrateAggregateExports },
264
+ { name: '导出的注意事项', fn: exportCaveats }
265
+ ];
266
+ if (exampleNum === 0) {
267
+ runAllExportExamples();
268
+ }
269
+ else if (exampleNum > 0 && exampleNum < examples.length) {
270
+ console.log(`\n运行示例 ${exampleNum}: ${examples[exampleNum].name}\n`);
271
+ console.log('='.repeat(50));
272
+ examples[exampleNum].fn();
273
+ console.log('='.repeat(50));
274
+ }
275
+ else {
276
+ console.log(`可用的示例:
277
+ ${examples.slice(1).map((ex, idx) => ` ${idx + 1}. ${ex.name}`).join('\n')}
278
+
279
+ 使用方法: ts-node 02-导出语法.ts [示例编号]`);
280
+ }
281
+ }