Writing JavaScript by doanchienthangdev/omgkit
npx skills add https://github.com/doanchienthangdev/omgkit --skill 'Writing JavaScript'// 现代解构与展开语法
const { name, email, role = 'user' } = user;
const settings = { ...defaults, theme: 'dark' };
const [first, ...rest] = items;
// 可选链与空值合并
const street = user?.address?.street ?? 'Unknown';
config.timeout ??= 5000;
// 带错误处理的异步/等待
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
}
// 函数式组合
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const processData = pipe(filter(isValid), map(transform), reduce(aggregate, []));
| 功能 | 描述 | 指南 |
|---|---|---|
| 解构 | 从对象和数组中提取值 | 使用 const { a, b } = obj 或 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
const [x, y] = arr| 展开运算符 | 扩展可迭代对象并合并对象 | 使用 ... 进行浅拷贝和合并 |
| 可选链 | 对可能为空的值进行安全的属性访问 | 使用 ?. 避免“无法读取属性”错误 |
| 空值合并 | 仅对 null/undefined 提供默认值 | 使用 ?? 代替 ` |
| 异步/等待 | 清晰的异步代码流程 | 使用 try/catch 进行错误处理 |
| Promise 方法 | 并行和条件执行 | 使用 all、allSettled、race、any 实现并发 |
| 数组方法 | 函数式数组转换 | 使用 map、filter、reduce、find、at、toSorted |
| 类 | 带有私有字段的面向对象模式 | 使用 # 前缀表示真正的私有成员 |
| 模块 | 使用 ESM import/export 组织代码 | 使用命名导出和桶文件 |
| 迭代器 | 使用生成器进行自定义迭代 | 使用 function* 和 for...of 循环 |
// 并行执行
const [user, posts] = await Promise.all([fetchUser(id), fetchPosts(id)]);
// 处理混合的成功/失败结果
const results = await Promise.allSettled(ids.map(fetchUser));
const successful = results.filter(r => r.status === 'fulfilled').map(r => r.value);
const failed = results.filter(r => r.status === 'rejected').map(r => r.reason);
// 带指数退避的重试机制
async function withRetry(fn, maxRetries = 3, baseDelay = 1000) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise(r => setTimeout(r, baseDelay * Math.pow(2, attempt)));
}
}
}
// 带限制的并发执行
async function mapConcurrent(items, fn, limit = 5) {
const results = [];
const executing = new Set();
for (const item of items) {
const promise = fn(item).then(r => { executing.delete(promise); return r; });
executing.add(promise);
results.push(promise);
if (executing.size >= limit) await Promise.race(executing);
}
return Promise.all(results);
}
// 柯里化
const curry = fn => function curried(...args) {
return args.length >= fn.length ? fn(...args) : (...next) => curried(...args, ...next);
};
// 记忆化
const memoize = fn => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (!cache.has(key)) cache.set(key, fn(...args));
return cache.get(key);
};
};
// 不可变更新
const updateUser = (user, updates) => ({ ...user, ...updates, updatedAt: new Date() });
const addItem = (arr, item) => [...arr, item];
const removeAt = (arr, i) => [...arr.slice(0, i), ...arr.slice(i + 1)];
class Result {
constructor(value, error) { this.value = value; this.error = error; }
static ok(value) { return new Result(value, null); }
static err(error) { return new Result(null, error); }
isOk() { return this.error === null; }
map(fn) { return this.isOk() ? Result.ok(fn(this.value)) : this; }
unwrapOr(defaultValue) { return this.isOk() ? this.value : defaultValue; }
}
async function safeFetch(url) {
try {
const res = await fetch(url);
if (!res.ok) return Result.err(new Error(`HTTP ${res.status}`));
return Result.ok(await res.json());
} catch (e) { return Result.err(e); }
}
// 使用示例
const result = await safeFetch('/api/data');
const data = result.map(d => d.items).unwrapOr([]);
class EventEmitter {
constructor() { this.events = new Map(); }
on(event, listener) {
if (!this.events.has(event)) this.events.set(event, new Set());
this.events.get(event).add(listener);
return () => this.off(event, listener);
}
off(event, listener) { this.events.get(event)?.delete(listener); }
emit(event, ...args) {
this.events.get(event)?.forEach(listener => listener(...args));
}
once(event, listener) {
const wrapper = (...args) => { listener(...args); this.off(event, wrapper); };
return this.on(event, wrapper);
}
}
// Map 用于任意类型键的键值对
const cache = new Map();
cache.set(userObj, 'data'); // 对象作为键
for (const [key, value] of cache) { /* 迭代 */ }
// Set 用于唯一值和集合操作
const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);
const union = new Set([...setA, ...setB]);
const intersection = new Set([...setA].filter(x => setB.has(x)));
// WeakMap 用于避免内存泄漏的私有数据
const privateData = new WeakMap();
class Secret {
constructor(value) { privateData.set(this, { value }); }
getValue() { return privateData.get(this).value; }
}
| 推荐做法 | 避免做法 |
|---|---|
默认使用 const,仅在需要时使用 let | 使用 var 声明变量 |
使用 === 进行严格相等比较 | 使用 == 允许类型转换 |
| 使用 async/await 代替原始 Promise 链 | 使用 .then() 回调导致深层嵌套 |
| 使用可选链进行安全的属性访问 | 在每个层级手动进行空值检查 |
| 使用解构进行更清晰的参数提取 | 重复访问对象属性 |
| 使用模板字面量进行字符串插值 | 使用 + 进行字符串拼接 |
| 使用箭头函数作为回调 | 对简单回调使用函数表达式 |
| 显式处理 Promise 拒绝 | 忽略未处理的拒绝警告 |
| 使用模块 (ESM) 组织代码 | 污染全局命名空间 |
| 尽可能编写纯函数 | 编写具有隐藏副作用的函数 |
每周安装量
0
代码仓库
GitHub 星标数
3
首次出现
1970年1月1日
安全审计
// Modern destructuring and spread
const { name, email, role = 'user' } = user;
const settings = { ...defaults, theme: 'dark' };
const [first, ...rest] = items;
// Optional chaining and nullish coalescing
const street = user?.address?.street ?? 'Unknown';
config.timeout ??= 5000;
// Async/await with error handling
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('Failed to fetch:', error);
throw error;
}
}
// Functional composition
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const processData = pipe(filter(isValid), map(transform), reduce(aggregate, []));
| Feature | Description | Guide |
|---|---|---|
| Destructuring | Extract values from objects and arrays | Use const { a, b } = obj or const [x, y] = arr |
| Spread Operator | Expand iterables and merge objects | Use ... for shallow copies and merging |
| Optional Chaining | Safe property access on nullable values | Use ?. to avoid "cannot read property" errors |
| Nullish Coalescing | Default values for null/undefined only | Use ?? instead of ` |
| Async/Await | Clean asynchronous code flow | Use try/catch for error handling |
| Promise Methods | Parallel and conditional execution | Use all, allSettled, race, any for concurrency |
| Array Methods | Functional array transformations | Use map, filter, reduce, find, at, toSorted |
| Classes | Object-oriented patterns with private fields | Use # prefix for truly private members |
| Modules | ESM import/export for code organization | Use named exports and barrel files |
| Iterators | Custom iteration with generators | Use function* and for...of loops |
// Parallel execution
const [user, posts] = await Promise.all([fetchUser(id), fetchPosts(id)]);
// Handle mixed success/failure
const results = await Promise.allSettled(ids.map(fetchUser));
const successful = results.filter(r => r.status === 'fulfilled').map(r => r.value);
const failed = results.filter(r => r.status === 'rejected').map(r => r.reason);
// Retry with exponential backoff
async function withRetry(fn, maxRetries = 3, baseDelay = 1000) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise(r => setTimeout(r, baseDelay * Math.pow(2, attempt)));
}
}
}
// Concurrent execution with limit
async function mapConcurrent(items, fn, limit = 5) {
const results = [];
const executing = new Set();
for (const item of items) {
const promise = fn(item).then(r => { executing.delete(promise); return r; });
executing.add(promise);
results.push(promise);
if (executing.size >= limit) await Promise.race(executing);
}
return Promise.all(results);
}
// Currying
const curry = fn => function curried(...args) {
return args.length >= fn.length ? fn(...args) : (...next) => curried(...args, ...next);
};
// Memoization
const memoize = fn => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (!cache.has(key)) cache.set(key, fn(...args));
return cache.get(key);
};
};
// Immutable updates
const updateUser = (user, updates) => ({ ...user, ...updates, updatedAt: new Date() });
const addItem = (arr, item) => [...arr, item];
const removeAt = (arr, i) => [...arr.slice(0, i), ...arr.slice(i + 1)];
class Result {
constructor(value, error) { this.value = value; this.error = error; }
static ok(value) { return new Result(value, null); }
static err(error) { return new Result(null, error); }
isOk() { return this.error === null; }
map(fn) { return this.isOk() ? Result.ok(fn(this.value)) : this; }
unwrapOr(defaultValue) { return this.isOk() ? this.value : defaultValue; }
}
async function safeFetch(url) {
try {
const res = await fetch(url);
if (!res.ok) return Result.err(new Error(`HTTP ${res.status}`));
return Result.ok(await res.json());
} catch (e) { return Result.err(e); }
}
// Usage
const result = await safeFetch('/api/data');
const data = result.map(d => d.items).unwrapOr([]);
class EventEmitter {
constructor() { this.events = new Map(); }
on(event, listener) {
if (!this.events.has(event)) this.events.set(event, new Set());
this.events.get(event).add(listener);
return () => this.off(event, listener);
}
off(event, listener) { this.events.get(event)?.delete(listener); }
emit(event, ...args) {
this.events.get(event)?.forEach(listener => listener(...args));
}
once(event, listener) {
const wrapper = (...args) => { listener(...args); this.off(event, wrapper); };
return this.on(event, wrapper);
}
}
// Map for key-value with any type keys
const cache = new Map();
cache.set(userObj, 'data'); // Object as key
for (const [key, value] of cache) { /* iterate */ }
// Set for unique values and operations
const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);
const union = new Set([...setA, ...setB]);
const intersection = new Set([...setA].filter(x => setB.has(x)));
// WeakMap for private data without memory leaks
const privateData = new WeakMap();
class Secret {
constructor(value) { privateData.set(this, { value }); }
getValue() { return privateData.get(this).value; }
}
| Do | Avoid |
|---|---|
Use const by default, let only when needed | Using var for variable declarations |
Use === for strict equality comparisons | Using == which allows type coercion |
| Use async/await over raw promise chains | Deep nesting with .then() callbacks |
| Use optional chaining for safe property access | Manual null checks at every level |
| Use destructuring for cleaner parameter extraction | Accessing object properties repeatedly |
| Use template literals for string interpolation | String concatenation with + |
Weekly Installs
0
Repository
GitHub Stars
3
First Seen
Jan 1, 1970
Security Audits
Flutter应用架构设计指南:分层结构、数据层实现与最佳实践
4,000 周安装
| Use arrow functions for callbacks |
| Using function expressions for simple callbacks |
| Handle promise rejections explicitly | Ignoring unhandled rejection warnings |
| Use modules (ESM) for code organization | Polluting the global namespace |
| Write pure functions when possible | Functions with hidden side effects |