@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,366 @@
1
+ "use strict";
2
+ /**
3
+ * ESM 导入语法
4
+ * ============
5
+ * 本文件详细介绍 ESM 的各种导入方式
6
+ * 包括命名导入、默认导入、动态导入等
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ // #region 示例1: 命名导入(Named Imports)
10
+ /**
11
+ * 命名导入:导入模块的命名导出
12
+ * 必须使用花括号,名称必须与导出的名称匹配
13
+ */
14
+ function demonstrateNamedImports() {
15
+ console.log(`=== 命名导入 ===
16
+
17
+ 语法形式1: 导入单个命名导出
18
+ import { name } from "./module.js";
19
+
20
+ 语法形式2: 导入多个命名导出
21
+ import { name1, name2, name3 } from "./module.js";
22
+
23
+ 语法形式3: 导入时重命名
24
+ import { originalName as newName } from "./module.js";
25
+
26
+ 语法形式4: 导入所有命名导出为命名空间对象
27
+ import * as moduleName from "./module.js";
28
+
29
+ 示例代码:
30
+ ---
31
+ // math.js 导出
32
+ export const PI = 3.14159;
33
+ export function add(a, b) { return a + b; }
34
+
35
+ // 导入方式1: 导入特定的导出
36
+ import { PI, add } from "./math.js";
37
+ console.log(PI); // 3.14159
38
+ console.log(add(2, 3)); // 5
39
+
40
+ // 导入方式2: 重命名避免冲突
41
+ import { PI as MathPI } from "./math.js";
42
+ const PI = 3.14; // 本地变量
43
+ console.log(MathPI); // 3.14159
44
+
45
+ // 导入方式3: 命名空间导入
46
+ import * as Math from "./math.js";
47
+ console.log(Math.PI); // 3.14159
48
+ console.log(Math.add(2, 3)); // 5
49
+ ---
50
+
51
+ 特点:
52
+ ✓ 明确知道导入了哪些内容
53
+ ✓ 支持 Tree Shaking
54
+ ✓ 可以重命名避免命名冲突
55
+ ✓ 命名空间导入会创建一个对象包含所有导出
56
+ `);
57
+ }
58
+ // #endregion
59
+ // #region 示例2: 默认导入(Default Import)
60
+ /**
61
+ * 默认导入:导入模块的默认导出
62
+ * 不使用花括号,可以使用任意名称
63
+ */
64
+ function demonstrateDefaultImport() {
65
+ console.log(`=== 默认导入 ===
66
+
67
+ 语法:
68
+ import myName from "./module.js";
69
+
70
+ 示例代码:
71
+ ---
72
+ // calculator.js 导出
73
+ export default class Calculator {
74
+ add(a, b) { return a + b; }
75
+ }
76
+
77
+ // 导入(可以使用任意名称)
78
+ import Calculator from "./calculator.js";
79
+ import Calc from "./calculator.js"; // 也可以
80
+ import MyCalc from "./calculator.js"; // 也可以
81
+
82
+ const calc = new Calculator();
83
+ console.log(calc.add(2, 3)); // 5
84
+ ---
85
+
86
+ 特点:
87
+ ✓ 不使用花括号
88
+ ✓ 可以使用任意名称
89
+ ✓ 每个模块只能有一个默认导出
90
+ ✓ 适合导入模块的主要功能
91
+ `);
92
+ }
93
+ // #endregion
94
+ // #region 示例3: 混合导入
95
+ /**
96
+ * 混合导入:同时导入默认导出和命名导出
97
+ */
98
+ function demonstrateMixedImports() {
99
+ console.log(`=== 混合导入 ===
100
+
101
+ 语法:
102
+ import defaultExport, { named1, named2 } from "./module.js";
103
+
104
+ 示例代码:
105
+ ---
106
+ // utils.js 导出
107
+ export const VERSION = "1.0.0";
108
+ export function helper() { return "help"; }
109
+ export default class Utils {
110
+ static main() { return "main"; }
111
+ }
112
+
113
+ // 导入
114
+ import Utils, { VERSION, helper } from "./utils.js";
115
+
116
+ console.log(Utils.main()); // "main"
117
+ console.log(VERSION); // "1.0.0"
118
+ console.log(helper()); // "help"
119
+ ---
120
+
121
+ 注意:
122
+ - 默认导入必须写在前面
123
+ - 命名导入使用花括号包裹
124
+ - 两者之间用逗号分隔
125
+ `);
126
+ }
127
+ // #endregion
128
+ // #region 示例4: 动态导入(Dynamic Import)
129
+ /**
130
+ * 动态导入:在运行时按需加载模块
131
+ * 返回一个 Promise,支持异步加载
132
+ */
133
+ async function demonstrateDynamicImport() {
134
+ console.log(`=== 动态导入 ===
135
+
136
+ 语法:
137
+ const module = await import("./module.js");
138
+
139
+ 特点:
140
+ 1. 运行时加载:可以在任何地方使用
141
+ 2. 返回 Promise:支持异步操作
142
+ 3. 按需加载:只在需要时才加载模块
143
+ 4. 条件加载:可以根据条件决定是否加载
144
+
145
+ 示例1: 基本用法
146
+ ---
147
+ // 使用 await
148
+ async function loadModule() {
149
+ const module = await import("./math.js");
150
+ console.log(module.add(2, 3));
151
+ }
152
+
153
+ // 使用 .then()
154
+ import("./math.js").then(module => {
155
+ console.log(module.add(2, 3));
156
+ });
157
+ ---
158
+
159
+ 示例2: 条件加载
160
+ ---
161
+ async function loadFeature(featureName) {
162
+ if (featureName === "advanced") {
163
+ const module = await import("./advanced.js");
164
+ return module.default;
165
+ } else {
166
+ const module = await import("./basic.js");
167
+ return module.default;
168
+ }
169
+ }
170
+ ---
171
+
172
+ 示例3: 访问导出内容
173
+ ---
174
+ const module = await import("./utils.js");
175
+
176
+ // 访问默认导出
177
+ const DefaultExport = module.default;
178
+
179
+ // 访问命名导出
180
+ const { VERSION, helper } = module;
181
+ // 或
182
+ console.log(module.VERSION);
183
+ console.log(module.helper());
184
+ ---
185
+
186
+ 使用场景:
187
+ - 代码分割:减少初始加载时间
188
+ - 按需加载:只在需要时加载功能
189
+ - 条件加载:根据用户操作或环境加载
190
+ - 懒加载:延迟加载非关键资源
191
+ `);
192
+ }
193
+ // #endregion
194
+ // #region 示例5: 仅执行导入(Side Effect Import)
195
+ /**
196
+ * 仅执行导入:导入模块但不使用其导出
197
+ * 用于执行模块的副作用(如注册、初始化等)
198
+ */
199
+ function demonstrateSideEffectImport() {
200
+ console.log(`=== 仅执行导入 ===
201
+
202
+ 语法:
203
+ import "./module.js";
204
+
205
+ 示例代码:
206
+ ---
207
+ // polyfill.js
208
+ if (!Array.prototype.includes) {
209
+ Array.prototype.includes = function(item) {
210
+ return this.indexOf(item) !== -1;
211
+ };
212
+ }
213
+ console.log("Polyfill loaded");
214
+
215
+ // main.js
216
+ import "./polyfill.js"; // 执行 polyfill,但不导入任何内容
217
+
218
+ // 现在可以使用 includes 方法
219
+ console.log([1, 2, 3].includes(2));
220
+ ---
221
+
222
+ 使用场景:
223
+ - 加载 polyfills
224
+ - 注册全局组件或插件
225
+ - 执行初始化代码
226
+ - 导入 CSS 文件(在构建工具中)
227
+
228
+ 注意:
229
+ - 模块会被执行,但不会导入任何绑定
230
+ - 模块的副作用会生效
231
+ - 适合只需要执行代码,不需要导出的场景
232
+ `);
233
+ }
234
+ // #endregion
235
+ // #region 示例6: 导入的注意事项
236
+ function importCaveats() {
237
+ console.log(`=== 导入的注意事项 ===
238
+
239
+ 1. 导入路径必须是字符串字面量:
240
+ ---
241
+ // ❌ 错误:不能使用变量
242
+ const modulePath = "./math.js";
243
+ import { add } from modulePath; // SyntaxError
244
+
245
+ // ✓ 正确:使用动态导入
246
+ const modulePath = "./math.js";
247
+ const module = await import(modulePath);
248
+ ---
249
+
250
+ 2. 导入语句会被提升(Hoisting):
251
+ ---
252
+ console.log(add(2, 3)); // 可以在导入前使用
253
+ import { add } from "./math.js";
254
+
255
+ // 实际执行顺序:
256
+ // 1. 先执行 import
257
+ // 2. 再执行 console.log
258
+ ---
259
+
260
+ 3. 导入的绑定是只读的:
261
+ ---
262
+ import { count } from "./counter.js";
263
+ count = 10; // TypeError: Assignment to constant variable
264
+
265
+ // 但如果导出的是对象,可以修改对象的属性
266
+ import { config } from "./config.js";
267
+ config.debug = true; // ✓ 可以修改属性
268
+ ---
269
+
270
+ 4. 导入语句必须在顶层:
271
+ ---
272
+ // ❌ 错误:不能在条件语句中导入
273
+ if (condition) {
274
+ import { add } from "./math.js"; // SyntaxError
275
+ }
276
+
277
+ // ✓ 正确:使用动态导入
278
+ if (condition) {
279
+ const { add } = await import("./math.js");
280
+ }
281
+ ---
282
+
283
+ 5. 文件扩展名:
284
+ ---
285
+ // Node.js ESM 要求完整的文件扩展名
286
+ import { add } from "./math.js"; // ✓ 正确
287
+ import { add } from "./math"; // ❌ 错误(Node.js)
288
+
289
+ // 浏览器和构建工具可能有不同的要求
290
+ // 建议始终包含扩展名以保持一致性
291
+ ---
292
+
293
+ 6. 循环依赖:
294
+ ---
295
+ // a.js
296
+ import { b } from "./b.js";
297
+ export const a = "a";
298
+ console.log(b); // undefined (b 还未初始化)
299
+
300
+ // b.js
301
+ import { a } from "./a.js";
302
+ export const b = "b";
303
+ console.log(a); // undefined (a 还未初始化)
304
+
305
+ // 避免循环依赖,或使用函数延迟访问
306
+ ---
307
+ `);
308
+ }
309
+ // #endregion
310
+ // 运行所有示例的函数
311
+ async function runAllExamples() {
312
+ console.log(`
313
+ ${'='.repeat(50)}
314
+ 运行所有示例
315
+ ${'='.repeat(50)}
316
+ `);
317
+ demonstrateNamedImports();
318
+ console.log('\n' + '-'.repeat(50) + '\n');
319
+ demonstrateDefaultImport();
320
+ console.log('\n' + '-'.repeat(50) + '\n');
321
+ demonstrateMixedImports();
322
+ console.log('\n' + '-'.repeat(50) + '\n');
323
+ await demonstrateDynamicImport();
324
+ console.log('\n' + '-'.repeat(50) + '\n');
325
+ demonstrateSideEffectImport();
326
+ console.log('\n' + '-'.repeat(50) + '\n');
327
+ importCaveats();
328
+ console.log('\n' + '='.repeat(50));
329
+ }
330
+ // 主函数:根据参数运行指定示例
331
+ if (require.main === module) {
332
+ const args = process.argv.slice(2);
333
+ const exampleNum = args[0] ? parseInt(args[0]) : 0;
334
+ const examples = [
335
+ { name: '所有示例', fn: runAllExamples },
336
+ { name: '命名导入', fn: demonstrateNamedImports },
337
+ { name: '默认导入', fn: demonstrateDefaultImport },
338
+ { name: '混合导入', fn: demonstrateMixedImports },
339
+ { name: '动态导入', fn: demonstrateDynamicImport },
340
+ { name: '仅执行导入', fn: demonstrateSideEffectImport },
341
+ { name: '导入的注意事项', fn: importCaveats }
342
+ ];
343
+ if (exampleNum === 0) {
344
+ void runAllExamples();
345
+ }
346
+ else if (exampleNum > 0 && exampleNum < examples.length) {
347
+ console.log(`\n运行示例 ${exampleNum}: ${examples[exampleNum].name}\n`);
348
+ console.log('='.repeat(50));
349
+ // 动态导入示例是异步的
350
+ if (exampleNum === 4) {
351
+ void examples[exampleNum].fn().then(() => {
352
+ console.log('='.repeat(50));
353
+ });
354
+ }
355
+ else {
356
+ examples[exampleNum].fn();
357
+ console.log('='.repeat(50));
358
+ }
359
+ }
360
+ else {
361
+ console.log(`可用的示例:
362
+ ${examples.slice(1).map((ex, idx) => ` ${idx + 1}. ${ex.name}`).join('\n')}
363
+
364
+ 使用方法: ts-node 03-导入语法.ts [示例编号]`);
365
+ }
366
+ }