@moon791017/neo-skills 1.0.24 → 1.0.25
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.
- package/GEMINI.md +2 -0
- package/README.md +6 -2
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/skills/neo-javascript/SKILL.md +125 -0
- package/skills/neo-javascript/reference/anti-patterns.md +296 -0
- package/skills/neo-javascript/reference/coding-style.md +112 -0
- package/skills/neo-javascript/reference/patterns.md +280 -0
package/GEMINI.md
CHANGED
|
@@ -107,3 +107,5 @@ When interacting with this codebase or using the extension, the agent follows th
|
|
|
107
107
|
* **Swift 專家:** 支援 Swift 5.0 至 6.0+ 的現代開發模式,涵蓋 SwiftUI、Structured Concurrency 與記憶體安全。
|
|
108
108
|
|
|
109
109
|
* **SwiftUI 專家:** 支援 iOS 16.0+ 與 Swift 5.0+ 的現代開發模式,專注於 NavigationStack、Observation 框架、資料流架構及高效能視圖設計。
|
|
110
|
+
|
|
111
|
+
* **JavaScript 現代語法專家:** 跨版本 JavaScript 專家 (ES6-ES2025+),專注於現代化語法、模組系統與高效能開發模式。
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Neo Skills
|
|
2
2
|
|
|
3
3
|
[](https://github.com/Benknightdark/neo-skills/actions/workflows/test-on-develop.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@moon791017/neo-skills)
|
|
4
5
|
|
|
5
6
|

|
|
6
7
|
|
|
@@ -52,10 +53,13 @@
|
|
|
52
53
|
* **Swift 5.0+ 專家 (`skills/neo-swift`)**:支援從基礎語法到 Swift 6 的現代開發模式,涵蓋 SwiftUI、Structured Concurrency、記憶體安全以及高效能 App 開發指引。
|
|
53
54
|
* **SwiftUI 專家 (`skills/neo-swift-ui`)**:支援 iOS 16.0+ 與 Swift 5.0+ 的現代開發模式,專注於 NavigationStack、Observation 框架、資料流架構及高效能視圖設計。
|
|
54
55
|
|
|
55
|
-
### 8.
|
|
56
|
+
### 8. JavaScript 開發專家
|
|
57
|
+
* **JavaScript 現代語法專家 (`skills/neo-javascript`)**:跨版本 JavaScript 專家 (ES6 - ES2025+),專注於現代化語法、模組系統與高效能開發模式。
|
|
58
|
+
|
|
59
|
+
### 9. 需求釐清助手
|
|
56
60
|
* **需求釐清**:系統化引導用戶釐清模糊需求,並將其轉化為結構化的規格文件(背景、功能、約束、驗收標準)。
|
|
57
61
|
|
|
58
|
-
###
|
|
62
|
+
### 10. 安全守衛 (Security Guard)
|
|
59
63
|
* **主動防護 (`secret-guard.ts`)**:作為 CLI 的中介軟體 (Hook),自動攔截並掃描所有工具執行的參數。若偵測到敏感資訊(如環境設定檔、私鑰、雲端憑證等)將強制阻擋執行,防止機密外洩。
|
|
60
64
|
|
|
61
65
|
## 📂 系統架構
|
package/gemini-extension.json
CHANGED
package/package.json
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: neo-javascript
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
category: "Core"
|
|
5
|
+
description: "跨版本 JavaScript 專家技能 (ES6 - ES2025+)。支援現代前端與純 JavaScript 開發模式,涵蓋 Arrow Functions 到 Iterator Helpers 的全方位演進。"
|
|
6
|
+
compatibility: "Supports ES6 (ES2015) through ES2025 and Stage 3+ proposals. Adaptive to modern browser environments and pure JS runtimes."
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Modern JavaScript (ES6+) Expert Skill
|
|
10
|
+
|
|
11
|
+
## Trigger On
|
|
12
|
+
- The user asks to write, debug, refactor, or review JavaScript code.
|
|
13
|
+
- The project directory contains `*.js`, `*.mjs`, or JavaScript configuration files (e.g., `eslint.config.js`, `vite.config.js`).
|
|
14
|
+
- HTML files (`*.html`) or Razor views (`*.cshtml`) contain inline `<script>` blocks or reference external `.js` files via `<script src="...">`.
|
|
15
|
+
- The target runtime is a modern browser (Chrome 80+, Firefox 78+, Safari 14+) or a pure JS environment.
|
|
16
|
+
- Code modernization is needed (e.g., converting `var` to `const`/`let`, callbacks to `async`/`await`, legacy scripts to ESM).
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
1. **Perceive (Environment Awareness):**
|
|
20
|
+
- Inspect ESLint / Biome configuration to identify the project's `ecmaVersion` and coding conventions.
|
|
21
|
+
- Determine runtime target: browser (check for DOM APIs, bundler config like `vite.config.js`, `webpack.config.js`).
|
|
22
|
+
- Detect JavaScript embedded in HTML (`*.html`) or Razor views (`*.cshtml`): identify inline `<script>` blocks and external `<script src="...">` references. For `.cshtml` files, note the interplay with Razor syntax (`@` directives, `@section Scripts`).
|
|
23
|
+
- Identify the effective ES version upper limit based on the runtime/transpiler configuration (e.g., Babel targets, TypeScript `target`, browserslist). For inline scripts without a build pipeline, default to the browser's native ES support.
|
|
24
|
+
2. **Reason (Planning Phase):**
|
|
25
|
+
- Evaluate the modernization level of the current code to determine the refactoring strategy.
|
|
26
|
+
- In environments targeting older runtimes (e.g., IE11 via Babel), avoid using features without polyfill support, but prioritize using `const`/`let`, arrow functions, and template literals.
|
|
27
|
+
- In modern environments (modern browsers), actively adopt new features to reduce boilerplate code.
|
|
28
|
+
- Be aware of browser-specific concerns (DOM manipulation, Web APIs, rendering performance).
|
|
29
|
+
3. **Act (Execution Phase):**
|
|
30
|
+
- Write high-quality code using modern syntax to improve readability and maintainability.
|
|
31
|
+
- Implement immutable data patterns (spread operators, `Object.freeze`, `structuredClone`, immutable array methods).
|
|
32
|
+
- Utilize `async`/`await` and `Promise` composition for asynchronous operations.
|
|
33
|
+
- Prefer ESM (`import`/`export`) as the standard module system.
|
|
34
|
+
4. **Validate (Standard Validation):**
|
|
35
|
+
- Validate strict equality (`===`) usage and absence of `var` declarations.
|
|
36
|
+
- Check if asynchronous operations correctly handle errors (`try`/`catch` around `await`, `.catch()` on Promises).
|
|
37
|
+
- Ensure code avoids common security pitfalls (no `eval()`, no prototype pollution, no `innerHTML` with unsanitized input).
|
|
38
|
+
- Verify naming conventions follow community standards (camelCase for variables/functions, PascalCase for classes).
|
|
39
|
+
|
|
40
|
+
## Feature Roadmap (ES6 - ES2025+)
|
|
41
|
+
|
|
42
|
+
### ES6 & ES2016-ES2019 (Origin)
|
|
43
|
+
- **Arrow Functions:** `(a, b) => a + b` concise function syntax with lexical `this` binding.
|
|
44
|
+
- **`let` / `const`:** Block-scoped variable declarations replacing `var`.
|
|
45
|
+
- **Template Literals:** `` `Hello, ${name}!` `` for string interpolation and multi-line strings.
|
|
46
|
+
- **Destructuring:** `const { id, name } = user;` extract values from objects and arrays.
|
|
47
|
+
- **Default / Rest / Spread:** Default parameters, `...rest` parameters, and `...spread` for arrays/objects.
|
|
48
|
+
- **Classes:** `class` syntax for prototype-based inheritance with `constructor`, `extends`, and `super`.
|
|
49
|
+
- **Promises:** `new Promise((resolve, reject) => ...)` for asynchronous flow control.
|
|
50
|
+
- **Modules:** `import` / `export` for modular code organization (ES Modules).
|
|
51
|
+
- **Symbol / Map / Set:** New primitive type and collection data structures.
|
|
52
|
+
- **String Methods (ES6):** `includes()`, `startsWith()`, `endsWith()` for easier string searching.
|
|
53
|
+
- **Array Methods (ES6):** `Array.from()`, `Array.of()`, `find()`, `findIndex()` for enhanced array manipulation.
|
|
54
|
+
- **Number/Math Methods (ES6):** `Number.isInteger()`, `Number.isNaN()`, `Math.trunc()`, `Math.sign()`.
|
|
55
|
+
- **Generators & Iterators:** `function*` and `for...of` for lazy iteration.
|
|
56
|
+
- **`async` / `await` (ES2017):** Syntactic sugar for Promise-based asynchronous code.
|
|
57
|
+
- **Object.values / Object.entries (ES2017):** Iterate over object values and key-value pairs.
|
|
58
|
+
- **Rest / Spread Properties (ES2018):** `{ ...obj }` for object shallow cloning and rest extraction.
|
|
59
|
+
- **`Promise.finally` (ES2018):** Execute cleanup logic regardless of fulfillment or rejection.
|
|
60
|
+
- **Async Iteration (ES2018):** `for await...of` for consuming async iterables.
|
|
61
|
+
- **`Array.flat` / `flatMap` (ES2019):** Flatten nested arrays and map-then-flatten in one step.
|
|
62
|
+
- **`Object.fromEntries` (ES2019):** Convert key-value pairs back into an object.
|
|
63
|
+
- **Optional Catch Binding (ES2019):** `catch { }` without requiring the error parameter.
|
|
64
|
+
|
|
65
|
+
### ES2020 & ES2021 (Foundation)
|
|
66
|
+
- **Optional Chaining (`?.`):** Safely access deeply nested properties without manual null checks.
|
|
67
|
+
- **Nullish Coalescing (`??`):** Provide defaults only for `null`/`undefined`, unlike `||` which also catches `0`, `""`, `false`.
|
|
68
|
+
- **`BigInt`:** Arbitrary-precision integer arithmetic via `123n` literal syntax.
|
|
69
|
+
- **`Promise.allSettled()`:** Wait for all promises to complete regardless of rejection.
|
|
70
|
+
- **`globalThis`:** Universal reference to the global object across all environments.
|
|
71
|
+
- **Dynamic `import()`:** Load modules conditionally or lazily at runtime.
|
|
72
|
+
- **Logical Assignment (`&&=`, `||=`, `??=`):** Combine logical operators with assignment for concise state updates.
|
|
73
|
+
- **`String.prototype.replaceAll()`:** Replace all occurrences without regex.
|
|
74
|
+
- **`Promise.any()`:** Resolve with the first fulfilled promise, reject only if all reject.
|
|
75
|
+
- **Numeric Separators:** `1_000_000` for readable large numbers.
|
|
76
|
+
|
|
77
|
+
### ES2022 & ES2023 (Productivity)
|
|
78
|
+
- **Top-level `await`:** Use `await` directly in ESM modules without wrapping in an async function.
|
|
79
|
+
- **Error Cause (`{ cause }`):** Chain errors to preserve root cause context.
|
|
80
|
+
- **`Array.at()`:** Negative indexing for arrays, e.g., `arr.at(-1)` for the last element.
|
|
81
|
+
- **`Object.hasOwn()`:** Safer, prototype-independent property check replacing `hasOwnProperty`.
|
|
82
|
+
- **Class Fields:** Public and private (`#field`) instance fields and methods.
|
|
83
|
+
- **RegExp Match Indices (`/d` flag):** Get start/end positions of captured groups.
|
|
84
|
+
- **Immutable Array Methods:** `toSorted()`, `toReversed()`, `toSpliced()`, `with()` — return new arrays without mutation.
|
|
85
|
+
- **`Array.findLast()` / `findLastIndex()`:** Search arrays from the end.
|
|
86
|
+
|
|
87
|
+
### ES2024 & ES2025+ (Cutting Edge)
|
|
88
|
+
- **`Promise.withResolvers()`:** Destructure `{ promise, resolve, reject }` for cleaner deferred patterns.
|
|
89
|
+
- **`Object.groupBy()` / `Map.groupBy()`:** Group array elements by a classifier function.
|
|
90
|
+
- **Set Methods:** `union()`, `intersection()`, `difference()`, `symmetricDifference()`, `isSubsetOf()`, `isSupersetOf()`, `isDisjointFrom()`.
|
|
91
|
+
- **Iterator Helpers:** `.map()`, `.filter()`, `.take()`, `.drop()`, `.flatMap()`, `.toArray()` on iterators.
|
|
92
|
+
- **`RegExp.escape()`:** Safely escape special characters for use in RegExp construction.
|
|
93
|
+
- **Import Attributes:** `import data from './data.json' with { type: 'json' }`.
|
|
94
|
+
- **Decorators (Stage 3):** Class and method decorators for cross-cutting concerns.
|
|
95
|
+
- **`Promise.try()`:** Safely start a promise chain from a synchronous or asynchronous function.
|
|
96
|
+
- **Well-formed Unicode Strings:** `String.prototype.isWellFormed()` and `toWellFormed()`.
|
|
97
|
+
- **Temporal API (Stage 3):** A modern replacement for the `Date` object, providing robust date/time arithmetic.
|
|
98
|
+
- **Explicit Resource Management (Stage 3):** `using` keyword with `Symbol.dispose` for deterministic cleanup.
|
|
99
|
+
|
|
100
|
+
## Coding Standards
|
|
101
|
+
- **Variable Declarations:** Always use `const` by default; use `let` only when reassignment is necessary. Never use `var`.
|
|
102
|
+
- **Modules:** Use ESM (`import`/`export`) as the default module system. Use `import()` for dynamic/lazy loading.
|
|
103
|
+
- **Immutability:** Prefer non-mutating array methods (`toSorted`, `toReversed`, `with`), spread operators, and `structuredClone` for deep copies.
|
|
104
|
+
- **Async Safety:** Always wrap `await` in `try`/`catch` or chain `.catch()`. Never leave Promises unhandled. Use `AbortController` for cancellable operations.
|
|
105
|
+
|
|
106
|
+
## Deliver
|
|
107
|
+
- **Runtime-Optimized Code:** Provide the most appropriate modern syntax code based on the target runtime and ES version.
|
|
108
|
+
- **Modernization Insights:** Provide specific refactoring suggestions for upgrading from older JavaScript syntax to new features (e.g., from callbacks to `async`/`await`, from `var` to `const`/`let`).
|
|
109
|
+
- **Syntax Explanations:** Clearly explain the design intent and advantages behind the modern JavaScript features used.
|
|
110
|
+
|
|
111
|
+
## Validate
|
|
112
|
+
- Ensure the provided code complies with the syntax specifications of the target ES version and runtime.
|
|
113
|
+
- Validate whether the code follows JavaScript best practices for error handling, null safety, and immutability.
|
|
114
|
+
- Confirm the code has good readability and modern conventions (e.g., proper use of destructuring, template literals, ESM).
|
|
115
|
+
|
|
116
|
+
## Documentation
|
|
117
|
+
### Official References
|
|
118
|
+
- [ECMAScript 2025 Language Specification](https://tc39.es/ecma262/)
|
|
119
|
+
- [TC39 Proposals (Stage 3+)](https://github.com/tc39/proposals/blob/main/README.md)
|
|
120
|
+
- [MDN Web Docs - JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
|
121
|
+
|
|
122
|
+
### Internal References
|
|
123
|
+
- [JavaScript Coding Style and Naming Conventions Guide](reference/coding-style.md)
|
|
124
|
+
- [JavaScript Anti-Patterns and Best Practices](reference/anti-patterns.md)
|
|
125
|
+
- [Modern JavaScript Patterns Guide](reference/patterns.md)
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# JavaScript Anti-Patterns & Best Practices
|
|
2
|
+
|
|
3
|
+
This document lists common mistakes (Anti-Patterns) in JavaScript development and their corresponding correct practices (Best Practices).
|
|
4
|
+
|
|
5
|
+
## 1. Variable Declarations and Scoping
|
|
6
|
+
|
|
7
|
+
### 1.1 Avoid `var` — Use `const` and `let`
|
|
8
|
+
|
|
9
|
+
**Problem**: `var` is function-scoped and hoisted, leading to unexpected behavior and bugs in loops and closures.
|
|
10
|
+
|
|
11
|
+
- **Bad**:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
for (var i = 0; i < 5; i++) {
|
|
15
|
+
setTimeout(() => console.log(i), 100); // Prints 5, 5, 5, 5, 5
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- **Good**:
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
for (let i = 0; i < 5; i++) {
|
|
23
|
+
setTimeout(() => console.log(i), 100); // Prints 0, 1, 2, 3, 4
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 1.2 Avoid Loose Equality (`==`)
|
|
28
|
+
|
|
29
|
+
**Problem**: `==` performs type coercion, leading to surprising comparisons (e.g., `0 == ''` is `true`, `null == undefined` is `true`).
|
|
30
|
+
|
|
31
|
+
- **Bad**:
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
if (value == null) { ... } // Catches both null and undefined — unclear intent
|
|
35
|
+
if (count == '0') { ... } // true due to type coercion
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- **Good**:
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
if (value === null || value === undefined) { ... } // Explicit intent
|
|
42
|
+
if (count === 0) { ... } // No coercion surprises
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 2. Asynchronous Programming
|
|
48
|
+
|
|
49
|
+
### 2.1 Avoid Callback Hell
|
|
50
|
+
|
|
51
|
+
**Problem**: Deeply nested callbacks make code unreadable and error handling fragile.
|
|
52
|
+
|
|
53
|
+
- **Bad**:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
getUser(id, (err, user) => {
|
|
57
|
+
if (err) return handleError(err);
|
|
58
|
+
getOrders(user.id, (err, orders) => {
|
|
59
|
+
if (err) return handleError(err);
|
|
60
|
+
getDetails(orders[0].id, (err, details) => {
|
|
61
|
+
// Deeply nested...
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **Good**:
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
try {
|
|
71
|
+
const user = await getUser(id);
|
|
72
|
+
const orders = await getOrders(user.id);
|
|
73
|
+
const details = await getDetails(orders[0].id);
|
|
74
|
+
} catch (err) {
|
|
75
|
+
handleError(err);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 2.2 Avoid Unhandled Promise Rejections
|
|
80
|
+
|
|
81
|
+
**Problem**: A Promise without `.catch()` or `try`/`catch` around `await` causes unhandled rejection warnings and unpredictable application states.
|
|
82
|
+
|
|
83
|
+
- **Bad**:
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
async function fetchData() {
|
|
87
|
+
const data = await api.get('/data'); // No error handling
|
|
88
|
+
return data;
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- **Good**:
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
async function fetchData() {
|
|
96
|
+
try {
|
|
97
|
+
const data = await api.get('/data');
|
|
98
|
+
return data;
|
|
99
|
+
} catch (err) {
|
|
100
|
+
throw new Error('Failed to fetch data', { cause: err });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 3. Memory & Performance
|
|
108
|
+
|
|
109
|
+
### 3.1 Avoid Event Listener and Timer Leaks
|
|
110
|
+
|
|
111
|
+
**Problem**: Adding event listeners or `setInterval` without cleanup leads to memory leaks, especially in single-page applications.
|
|
112
|
+
|
|
113
|
+
- **Bad**:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
function setup() {
|
|
117
|
+
window.addEventListener('resize', handleResize);
|
|
118
|
+
// Never removed — leaks when component is destroyed
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- **Good**:
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
const controller = new AbortController();
|
|
126
|
+
window.addEventListener('resize', handleResize, { signal: controller.signal });
|
|
127
|
+
// Cleanup: controller.abort();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 3.2 Avoid Blocking the Main Thread
|
|
131
|
+
|
|
132
|
+
**Problem**: CPU-intensive synchronous operations (huge loops, massive DOM updates, or heavy JSON parsing) block the main thread, freezing the UI and making the browser unresponsive.
|
|
133
|
+
|
|
134
|
+
- **Bad**:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
function processLargeData(items) {
|
|
138
|
+
// Blocks the UI thread completely for a long time
|
|
139
|
+
return items.map(item => expensiveComputation(item));
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- **Good**:
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// Use Web Workers for heavy computation, or chunking via setTimeout/requestAnimationFrame
|
|
147
|
+
function processDataInChunks(items) {
|
|
148
|
+
let index = 0;
|
|
149
|
+
function chunk() {
|
|
150
|
+
const end = Math.min(index + 100, items.length);
|
|
151
|
+
for (; index < end; index++) {
|
|
152
|
+
expensiveComputation(items[index]);
|
|
153
|
+
}
|
|
154
|
+
if (index < items.length) {
|
|
155
|
+
requestAnimationFrame(chunk); // Yield back to the browser
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
chunk();
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 4. Security
|
|
165
|
+
|
|
166
|
+
### 4.1 Avoid `eval()` and `innerHTML` with Untrusted Input
|
|
167
|
+
|
|
168
|
+
**Problem**: `eval()` executes arbitrary code; `innerHTML` with user input enables XSS attacks.
|
|
169
|
+
|
|
170
|
+
- **Bad**:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
element.innerHTML = userComment; // XSS vulnerability
|
|
174
|
+
eval(userInput); // Remote code execution
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
- **Good**:
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
element.textContent = userComment; // Safe
|
|
181
|
+
// For HTML rendering, use a sanitization library (e.g., DOMPurify)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 4.2 Avoid Mutating Function Parameters (Immutability)
|
|
185
|
+
|
|
186
|
+
**Problem**: Directly mutating input arguments causes hard-to-trace side effects. The caller's data is changed unexpectedly.
|
|
187
|
+
|
|
188
|
+
- **Bad**:
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
const addNewTag = (tags, newTag) => {
|
|
192
|
+
tags.push(newTag); // Mutates the original array
|
|
193
|
+
return tags;
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- **Good**:
|
|
198
|
+
|
|
199
|
+
```javascript
|
|
200
|
+
const addNewTag = (tags, newTag) => {
|
|
201
|
+
return [...tags, newTag]; // Returns a new array, keeps original data intact
|
|
202
|
+
};
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### 4.3 Avoid Prototype Pollution
|
|
206
|
+
|
|
207
|
+
**Problem**: Merging untrusted objects into existing objects can overwrite `Object.prototype` properties, leading to security vulnerabilities.
|
|
208
|
+
|
|
209
|
+
- **Bad**:
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
function merge(target, source) {
|
|
213
|
+
for (const key in source) {
|
|
214
|
+
target[key] = source[key]; // '__proto__' can be injected
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- **Good**:
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
function merge(target, source) {
|
|
223
|
+
for (const key of Object.keys(source)) {
|
|
224
|
+
if (key === '__proto__' || key === 'constructor') continue;
|
|
225
|
+
target[key] = source[key];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Or use structuredClone / Object.assign with null-prototype objects
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 5. Modern JavaScript Patterns
|
|
234
|
+
|
|
235
|
+
### 5.1 Variable Declarations (ES6+)
|
|
236
|
+
|
|
237
|
+
- **Legacy**: `var name = 'Alice';`
|
|
238
|
+
- **Modern**: `const name = 'Alice';` (Block-scoped, no hoisting surprises)
|
|
239
|
+
|
|
240
|
+
### 5.2 Async Flow (ES2017+)
|
|
241
|
+
|
|
242
|
+
- **Legacy**:
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
fetch('/api/data')
|
|
246
|
+
.then(res => res.json())
|
|
247
|
+
.then(data => console.log(data))
|
|
248
|
+
.catch(err => console.error(err));
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
- **Modern**:
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
try {
|
|
255
|
+
const res = await fetch('/api/data');
|
|
256
|
+
const data = await res.json();
|
|
257
|
+
console.log(data);
|
|
258
|
+
} catch (err) {
|
|
259
|
+
console.error(err);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 5.3 Default Values (ES2020+)
|
|
264
|
+
|
|
265
|
+
- **Legacy**: `const name = obj && obj.user && obj.user.name || 'default';`
|
|
266
|
+
- **Modern**: `const name = obj?.user?.name ?? 'default';` (Optional chaining + nullish coalescing)
|
|
267
|
+
|
|
268
|
+
### 5.4 Array Mutation (ES2023+)
|
|
269
|
+
|
|
270
|
+
- **Legacy**: `const sorted = [...arr].sort(compareFn);` (Manual copy to avoid mutation)
|
|
271
|
+
- **Modern**: `const sorted = arr.toSorted(compareFn);` (Returns a new sorted array)
|
|
272
|
+
|
|
273
|
+
### 5.5 Object Property Checking (ES2022+)
|
|
274
|
+
|
|
275
|
+
- **Legacy**: `if (obj.hasOwnProperty('key'))` (Can be overridden on the object)
|
|
276
|
+
- **Modern**: `if (Object.hasOwn(obj, 'key'))` (Static method, safe from prototype overriding)
|
|
277
|
+
|
|
278
|
+
### 5.6 Module System (ES6+)
|
|
279
|
+
|
|
280
|
+
- **Legacy**: `var cloneDeep = require('lodash/cloneDeep');` (CommonJS / Script tags)
|
|
281
|
+
- **Modern**: `import { cloneDeep } from 'lodash-es';` (ESM)
|
|
282
|
+
|
|
283
|
+
### 5.7 Logical Assignment (ES2021+)
|
|
284
|
+
|
|
285
|
+
- **Legacy**: `if (!obj.prop) { obj.prop = value; }` (Verbose and repetitive)
|
|
286
|
+
- **Modern**: `obj.prop ??= value;` (Concise nullish assignment)
|
|
287
|
+
|
|
288
|
+
### 5.8 String & Array Searching (ES6+)
|
|
289
|
+
|
|
290
|
+
- **Legacy**: `if (str.indexOf('text') !== -1)` (Returns index, requires `!== -1` check)
|
|
291
|
+
- **Modern**: `if (str.includes('text'))` (Returns boolean directly, clearer intent)
|
|
292
|
+
|
|
293
|
+
### 5.9 Object Grouping (ES2024+)
|
|
294
|
+
|
|
295
|
+
- **Legacy**: `users.reduce((acc, user) => { (acc[user.role] ||= []).push(user); return acc; }, {});` (Verbose reduce logic)
|
|
296
|
+
- **Modern**: `Object.groupBy(users, user => user.role);` (Clear intent, native support)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# JavaScript Coding Conventions
|
|
2
|
+
|
|
3
|
+
This guide follows community-established conventions from [MDN JavaScript Guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide), [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript), and [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html), aimed at improving development efficiency and maintaining project consistency.
|
|
4
|
+
|
|
5
|
+
## 1. Naming Conventions
|
|
6
|
+
|
|
7
|
+
Good naming is the core of self-documenting code and reduces communication overhead.
|
|
8
|
+
|
|
9
|
+
### 1.1 camelCase
|
|
10
|
+
Used for **variables**, **functions**, and **object properties**.
|
|
11
|
+
- **Variable**: `const userName = 'Alice';`
|
|
12
|
+
- **Function**: `function getUserById(id) { ... }`
|
|
13
|
+
- **Object Property**: `{ firstName: 'Bob', lastName: 'Smith' }`
|
|
14
|
+
|
|
15
|
+
### 1.2 PascalCase
|
|
16
|
+
Used for **classes**, **constructors**, and **components**.
|
|
17
|
+
- **Class**: `class UserManager { ... }`
|
|
18
|
+
- **React/UI Component**: `function NavBar() { ... }`
|
|
19
|
+
|
|
20
|
+
### 1.3 UPPER_SNAKE_CASE
|
|
21
|
+
Used for **module-level constants** and **configuration values**.
|
|
22
|
+
- **Constant**: `const MAX_RETRIES = 3;`
|
|
23
|
+
- **Config**: `const API_BASE_URL = 'https://api.example.com';`
|
|
24
|
+
|
|
25
|
+
### 1.4 Private Fields
|
|
26
|
+
Use the `#` prefix for **private class fields** (ES2022+).
|
|
27
|
+
- **Private field**: `#count = 0;`
|
|
28
|
+
- **Private method**: `#validate() { ... }`
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 2. File Organization
|
|
33
|
+
|
|
34
|
+
- **File naming**: Use `kebab-case` for file names (e.g., `user-service.js`, `auth-utils.mjs`).
|
|
35
|
+
- **Module type**: Use `.mjs` extension or `"type": "module"` in `package.json` for ESM.
|
|
36
|
+
- **Single responsibility**: One primary export per module file to facilitate tree-shaking and code navigation.
|
|
37
|
+
- **Import order**: External packages first, then internal modules. Separate groups with blank lines.
|
|
38
|
+
```javascript
|
|
39
|
+
// 1. External packages
|
|
40
|
+
import React, { useState } from 'react';
|
|
41
|
+
import { debounce } from 'lodash-es';
|
|
42
|
+
|
|
43
|
+
// 2. Internal modules
|
|
44
|
+
import { validateInput } from './utils/validation.js';
|
|
45
|
+
import { UserCard } from './components/user-card.js';
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 3. Formatting
|
|
51
|
+
|
|
52
|
+
### 3.1 K&R Style (Opening brace on same line)
|
|
53
|
+
The opening brace `{` stays on the same line as the statement. This is the standard JavaScript style.
|
|
54
|
+
```javascript
|
|
55
|
+
// Correct approach
|
|
56
|
+
function process() {
|
|
57
|
+
if (isReady) {
|
|
58
|
+
doWork();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3.2 Indentation and Spacing
|
|
64
|
+
- **Indentation**: Fixed at **2 spaces**. The use of Tab characters is prohibited to ensure consistent display across platforms.
|
|
65
|
+
- **Semicolons**: Be consistent within a project. If using semicolons, use them everywhere. If omitting (relying on ASI), do so consistently and understand the pitfalls.
|
|
66
|
+
- **Blank lines**: Leave one blank line between function declarations; use a single blank line to separate logical blocks within a function.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 4. Asynchronous Programming
|
|
71
|
+
|
|
72
|
+
- **Async/Await**: Prefer `async`/`await` over `.then()` chains for readability.
|
|
73
|
+
- **Error Handling**: Always wrap `await` calls in `try`/`catch` or use a utility wrapper.
|
|
74
|
+
- **AbortController**: Use `AbortController` for cancellable fetch requests, timers, and event listeners.
|
|
75
|
+
```javascript
|
|
76
|
+
async function getUserById(id, signal) {
|
|
77
|
+
const response = await fetch(`/api/users/${id}`, { signal });
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error(`HTTP ${response.status}`, { cause: response });
|
|
80
|
+
}
|
|
81
|
+
return response.json();
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 5. Modern JavaScript Best Practices
|
|
88
|
+
|
|
89
|
+
- **Variable Declarations (`const`/`let`)**: Use `const` by default. Use `let` only when the binding will be reassigned. Never use `var`.
|
|
90
|
+
- Recommended: `const users = [];`
|
|
91
|
+
- **Null/Undefined Checks**: Use nullish coalescing (`??`) and optional chaining (`?.`) instead of `||` and manual checks.
|
|
92
|
+
- Recommended: `const name = user?.profile?.name ?? 'Anonymous';`
|
|
93
|
+
- **Object/Array Initialization**: Use destructuring, spread operators, and shorthand property names.
|
|
94
|
+
- Recommended: `const { id, name } = user;`
|
|
95
|
+
- **Equality**: Always use `===` and `!==`. Never use `==` or `!=`.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 6. Commenting Conventions
|
|
100
|
+
|
|
101
|
+
- **JSDoc**: Public APIs and exported functions should use `/** ... */` JSDoc comments for IDE IntelliSense and documentation generation.
|
|
102
|
+
```javascript
|
|
103
|
+
/**
|
|
104
|
+
* Fetches a user by their unique identifier.
|
|
105
|
+
* @param {number} id - The user's ID.
|
|
106
|
+
* @param {AbortSignal} [signal] - Optional signal to cancel the request.
|
|
107
|
+
* @returns {Promise<User>} The user object.
|
|
108
|
+
*/
|
|
109
|
+
export async function getUserById(id, signal) { ... }
|
|
110
|
+
```
|
|
111
|
+
- **Logical Comments**: Comments should explain "Why" the processing is done this way, not repeat "What" the code does.
|
|
112
|
+
- **TODO/FIXME**: Use `// TODO:` for planned improvements and `// FIXME:` for known issues.
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# Modern JavaScript Patterns Guide
|
|
2
|
+
|
|
3
|
+
This document introduces recommended development patterns in ES6 through ES2025+, aiming to simplify code and improve reliability using modern syntax.
|
|
4
|
+
|
|
5
|
+
## 1. Module and Declaration Patterns
|
|
6
|
+
|
|
7
|
+
### 1.1 ESM Modules (ES6+)
|
|
8
|
+
**Recommendation**: Use `import`/`export` with named exports for tree-shaking compatibility.
|
|
9
|
+
```javascript
|
|
10
|
+
// Named exports (preferred for libraries)
|
|
11
|
+
export function formatDate(date) { ... }
|
|
12
|
+
export function parseDate(str) { ... }
|
|
13
|
+
|
|
14
|
+
// Default export (preferred for single-purpose modules)
|
|
15
|
+
export default class UserService { ... }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 1.2 Dynamic Import (ES2020+)
|
|
19
|
+
**Recommendation**: Lazy-load modules for code splitting and conditional loading.
|
|
20
|
+
```javascript
|
|
21
|
+
const { Chart } = await import('./chart.js');
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 1.3 Arrow Functions vs Function Declarations
|
|
25
|
+
**Recommendation**: Use arrow functions for callbacks and short expressions. Use function declarations for top-level named functions that benefit from hoisting.
|
|
26
|
+
```javascript
|
|
27
|
+
// Arrow functions for callbacks
|
|
28
|
+
const doubled = numbers.map(n => n * 2);
|
|
29
|
+
|
|
30
|
+
// Function declarations for top-level definitions
|
|
31
|
+
function processOrder(order) {
|
|
32
|
+
// ...
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 1.4 Logical Assignment (ES2021+)
|
|
37
|
+
**Recommendation**: Use logical assignment operators (`??=`, `||=`, `&&=`) to concisely update variables only when specific conditions are met.
|
|
38
|
+
```javascript
|
|
39
|
+
// ??= (Nullish coalescing assignment)
|
|
40
|
+
user.role ??= 'viewer'; // Assigns 'viewer' only if user.role is null or undefined
|
|
41
|
+
|
|
42
|
+
// ||= (Logical OR assignment)
|
|
43
|
+
config.timeout ||= 5000; // Assigns 5000 if config.timeout is falsy (e.g., 0, '', null)
|
|
44
|
+
|
|
45
|
+
// &&= (Logical AND assignment)
|
|
46
|
+
state.isReady &&= verifyStatus(); // Updates state.isReady only if it is already truthy
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 2. Data Structures and Immutability
|
|
52
|
+
|
|
53
|
+
### 2.1 Destructuring and Spread (ES6+)
|
|
54
|
+
**Recommendation**: Use destructuring to extract values and spread to create shallow copies.
|
|
55
|
+
```javascript
|
|
56
|
+
// Object destructuring with renaming and defaults
|
|
57
|
+
const { name: userName, role = 'viewer' } = user;
|
|
58
|
+
|
|
59
|
+
// Shallow clone with override
|
|
60
|
+
const updated = { ...config, timeout: 5000 };
|
|
61
|
+
|
|
62
|
+
// Array spread
|
|
63
|
+
const combined = [...listA, ...listB];
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2.2 Immutable Array Operations (ES2023+)
|
|
67
|
+
**Recommendation**: Use non-mutating array methods to avoid side effects.
|
|
68
|
+
```javascript
|
|
69
|
+
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name));
|
|
70
|
+
const reversed = items.toReversed();
|
|
71
|
+
const updated = items.with(2, 'newValue');
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2.3 Object Grouping (ES2024+)
|
|
75
|
+
**Recommendation**: Use `Object.groupBy()` instead of manual reduce-based grouping.
|
|
76
|
+
```javascript
|
|
77
|
+
const grouped = Object.groupBy(users, user => user.role);
|
|
78
|
+
// { admin: [...], editor: [...], viewer: [...] }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 2.4 Structured Cloning
|
|
82
|
+
**Recommendation**: Use `structuredClone()` for deep copies instead of `JSON.parse(JSON.stringify())`.
|
|
83
|
+
```javascript
|
|
84
|
+
const deepCopy = structuredClone(originalObject);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2.5 Modern Iterables & Array Creation (ES6+)
|
|
88
|
+
**Recommendation**: Use `Array.from()` to convert iterable objects (like NodeList or arguments) into true arrays, and utilize its built-in mapping capability.
|
|
89
|
+
```javascript
|
|
90
|
+
// Convert NodeList to Array and extract text content
|
|
91
|
+
const elements = document.querySelectorAll('.item');
|
|
92
|
+
const texts = Array.from(elements, el => el.textContent);
|
|
93
|
+
|
|
94
|
+
// Create an array of a specific length filled with values
|
|
95
|
+
const range = Array.from({ length: 5 }, (_, i) => i + 1); // [1, 2, 3, 4, 5]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2.6 String & Array Searching (ES6+)
|
|
99
|
+
**Recommendation**: Replace verbose `indexOf()` checks with `includes()`, `startsWith()`, `endsWith()`, and replace `filter()[0]` with `find()`.
|
|
100
|
+
```javascript
|
|
101
|
+
// String checking
|
|
102
|
+
const url = 'https://example.com';
|
|
103
|
+
const isHttps = url.startsWith('https'); // Preferred over url.indexOf('https') === 0
|
|
104
|
+
|
|
105
|
+
// Array searching
|
|
106
|
+
const targetUser = users.find(u => u.id === 123); // Preferred over users.filter(...)[0]
|
|
107
|
+
const hasAdmin = users.some(u => u.role === 'admin'); // Checking existence
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 3. Async Patterns and Promise Composition
|
|
113
|
+
|
|
114
|
+
### 3.1 async/await (ES2017+)
|
|
115
|
+
**Recommendation**: Prefer `async`/`await` over `.then()` chains for readability and maintainability.
|
|
116
|
+
```javascript
|
|
117
|
+
async function loadUserProfile(id) {
|
|
118
|
+
try {
|
|
119
|
+
const user = await fetchUser(id);
|
|
120
|
+
const posts = await fetchPosts(user.id);
|
|
121
|
+
return { user, posts };
|
|
122
|
+
} catch (err) {
|
|
123
|
+
throw new Error('Failed to load profile', { cause: err });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 3.2 Promise Composition
|
|
129
|
+
**Recommendation**: Choose the right Promise combinator for the use case.
|
|
130
|
+
```javascript
|
|
131
|
+
// All must succeed
|
|
132
|
+
const [users, posts] = await Promise.all([fetchUsers(), fetchPosts()]);
|
|
133
|
+
|
|
134
|
+
// All settle, handle individually
|
|
135
|
+
const results = await Promise.allSettled([taskA(), taskB()]);
|
|
136
|
+
|
|
137
|
+
// First to succeed
|
|
138
|
+
const fastest = await Promise.any([mirrorA(), mirrorB()]);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 3.3 Deferred Promise (ES2024+)
|
|
142
|
+
**Recommendation**: Use `Promise.withResolvers()` for externally controlled promises.
|
|
143
|
+
```javascript
|
|
144
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
145
|
+
setTimeout(() => resolve('done'), 1000);
|
|
146
|
+
const result = await promise;
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 3.4 Async Generators and Iteration (ES2018+)
|
|
150
|
+
**Recommendation**: Use async generators for streaming data processing.
|
|
151
|
+
```javascript
|
|
152
|
+
async function* fetchPages(url) {
|
|
153
|
+
let nextUrl = url;
|
|
154
|
+
while (nextUrl) {
|
|
155
|
+
const response = await fetch(nextUrl);
|
|
156
|
+
const data = await response.json();
|
|
157
|
+
yield data.items;
|
|
158
|
+
nextUrl = data.nextPage;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
for await (const page of fetchPages('/api/users')) {
|
|
163
|
+
processItems(page);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 4. Class Patterns and Encapsulation
|
|
170
|
+
|
|
171
|
+
### 4.1 ES6 Classes
|
|
172
|
+
**Recommendation**: Use `class` syntax with clear inheritance and `super` calls.
|
|
173
|
+
```javascript
|
|
174
|
+
class Animal {
|
|
175
|
+
constructor(name) {
|
|
176
|
+
this.name = name;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
speak() {
|
|
180
|
+
return `${this.name} makes a sound.`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
class Dog extends Animal {
|
|
185
|
+
speak() {
|
|
186
|
+
return `${this.name} barks.`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 4.2 Private Fields and Methods (ES2022+)
|
|
192
|
+
**Recommendation**: Use `#` prefix for true encapsulation, replacing the underscore convention.
|
|
193
|
+
```javascript
|
|
194
|
+
class Counter {
|
|
195
|
+
#count = 0;
|
|
196
|
+
|
|
197
|
+
increment() { this.#count++; }
|
|
198
|
+
get value() { return this.#count; }
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 4.3 Error Cause Chaining (ES2022+)
|
|
203
|
+
**Recommendation**: Preserve error context with the `cause` option.
|
|
204
|
+
```javascript
|
|
205
|
+
try {
|
|
206
|
+
await initializeService();
|
|
207
|
+
} catch (err) {
|
|
208
|
+
throw new Error('Service initialization failed', { cause: err });
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 4.4 Explicit Resource Management (ES2025+)
|
|
213
|
+
**Recommendation**: Use the `using` keyword for automatic and deterministic cleanup of resources (like file handles, database connections, or subscriptions).
|
|
214
|
+
```javascript
|
|
215
|
+
function processFile() {
|
|
216
|
+
using file = openFile('data.txt'); // Automatically closed when function exits
|
|
217
|
+
const data = file.read();
|
|
218
|
+
return data;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Async disposal
|
|
222
|
+
async function fetchAndProcess() {
|
|
223
|
+
await using connection = await db.connect();
|
|
224
|
+
return connection.query('SELECT * FROM users');
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 5. Set and Iterator Patterns (ES2025+)
|
|
231
|
+
|
|
232
|
+
### 5.1 Set Operations
|
|
233
|
+
**Recommendation**: Use native Set methods instead of manual implementations.
|
|
234
|
+
```javascript
|
|
235
|
+
const setA = new Set([1, 2, 3]);
|
|
236
|
+
const setB = new Set([2, 3, 4]);
|
|
237
|
+
|
|
238
|
+
const union = setA.union(setB); // Set {1, 2, 3, 4}
|
|
239
|
+
const intersection = setA.intersection(setB); // Set {2, 3}
|
|
240
|
+
const difference = setA.difference(setB); // Set {1}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 5.2 Iterator Helpers
|
|
244
|
+
**Recommendation**: Use lazy iterator methods for memory-efficient data processing.
|
|
245
|
+
```javascript
|
|
246
|
+
const firstFiveEven = Iterator.from(hugeArray)
|
|
247
|
+
.filter(n => n % 2 === 0)
|
|
248
|
+
.take(5)
|
|
249
|
+
.toArray();
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 6. Security and Performance
|
|
255
|
+
|
|
256
|
+
### 6.1 Input Sanitization
|
|
257
|
+
**Recommendation**: Never use `eval()`, `innerHTML` with unsanitized input, or `new Function()` with user input.
|
|
258
|
+
```javascript
|
|
259
|
+
// Safe DOM manipulation
|
|
260
|
+
element.textContent = userInput; // not element.innerHTML
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 6.2 AbortController for Resource Management
|
|
264
|
+
**Recommendation**: Use `AbortController` to cancel fetch requests, timers, and event listeners.
|
|
265
|
+
```javascript
|
|
266
|
+
const controller = new AbortController();
|
|
267
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
268
|
+
// Cancel if needed: controller.abort();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 6.3 Avoiding Memory Leaks
|
|
272
|
+
**Recommendation**: Use `WeakRef` and `WeakMap` for caches, and always clean up event listeners and intervals.
|
|
273
|
+
```javascript
|
|
274
|
+
// Use AbortController signal for automatic listener cleanup
|
|
275
|
+
const controller = new AbortController();
|
|
276
|
+
window.addEventListener('resize', handleResize, { signal: controller.signal });
|
|
277
|
+
|
|
278
|
+
// Cleanup all listeners at once
|
|
279
|
+
controller.abort();
|
|
280
|
+
```
|