web-utilities-native-js
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNative JavaScript Utility Patterns
原生JavaScript实用工具模式
Quick Guide: Prefer native JavaScript (ES2022-ES2025) over utility libraries. Usefor deep cloning,structuredClonefor grouping, ES2023 immutable array methods (Object.groupBy,toSorted,toReversed), and ES2025 Set methods for set operations. Only reach for utility libraries when native alternatives genuinely don't exist or lack needed features (cancel/flush on debounce, deep merge with array strategies).with
<critical_requirements>
**快速指南:**优先使用原生JavaScript(ES2022-ES2025)而非工具库。使用进行深度克隆,使用structuredClone进行分组,使用ES2023不可变数组方法(Object.groupBy、toSorted、toReversed),以及ES2025 Set方法进行集合操作。仅当原生替代方案确实不存在或缺少所需功能(如防抖的取消/刷新、带数组策略的深度合并)时,才考虑使用工具库。with
<critical_requirements>
CRITICAL: Before Using This Skill
重要提示:使用本技能之前
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,, named constants)import type
(You MUST use native ES2022+ methods before considering utility libraries - check this skill first)
(You MUST use immutable array methods (, , , ) instead of mutating methods)
toSortedtoReversedtoSplicedwith(You MUST use for deep cloning - NOT JSON.parse/JSON.stringify hacks)
structuredClone(You MUST define named constants for all numeric values - NO magic numbers in utility functions)
</critical_requirements>
Auto-detection: native JavaScript utilities, lodash alternative, ES2023 array methods, toSorted, toReversed, structuredClone, Object.groupBy, Set union, Set intersection, optional chaining, nullish coalescing, at(), findLast
When to use:
- Array manipulation (find, filter, sort, reverse, chunk, unique, group)
- Object operations (pick, omit, merge, clone, groupBy)
- Set operations (union, intersection, difference)
- Deep cloning without external libraries
- Function utilities (debounce, throttle, memoize)
When NOT to use:
- Complex deep merge with custom array-handling strategies - use a library
- Lazy evaluation chains over large datasets - lodash chains are optimized for this
- Objects containing functions that need cloning - cannot clone functions
structuredClone - Full-featured debounce/throttle with cancel, flush, leading/trailing - use a library
Key patterns covered:
- Safe property access (optional chaining + nullish coalescing replaces )
_.get - Immutable array operations (,
toSorted,toReversed,toSpliced)with - Deep cloning with (handles Map, Set, Date, circular refs)
structuredClone - /
Object.groupBy(ES2024 - replaces reduce-based grouping)Map.groupBy - ES2025 Set methods (union, intersection, difference, symmetricDifference)
- Object pick/omit, unique values, chunking, flattening
Detailed Resources:
- examples/core.md - Safe access, deep cloning, immutable arrays, findLast
- examples/arrays.md - Unique values, set operations, grouping, chunking, sorting
- examples/objects.md - Pick, omit, merge, mapKeys/mapValues, freeze
- reference.md - Decision frameworks, lodash-to-native table, red flags, anti-patterns
<philosophy>
所有代码必须遵循CLAUDE.md中的项目约定(短横线命名法、命名导出、导入顺序、、命名常量)import type
(在考虑使用工具库之前,必须优先使用原生ES2022+方法——先查阅本技能)
(必须使用不可变数组方法(、、、)而非可变方法)
toSortedtoReversedtoSplicedwith(必须使用进行深度克隆——禁止使用JSON.parse/JSON.stringify这类取巧方式)
structuredClone(必须为所有数值定义命名常量——工具函数中禁止使用魔法数字)
</critical_requirements>
**自动检测:**原生JavaScript工具、lodash替代方案、ES2023数组方法、toSorted、toReversed、structuredClone、Object.groupBy、Set并集、Set交集、可选链、空值合并、at()、findLast
适用场景:
- 数组操作(查找、过滤、排序、反转、分块、去重、分组)
- 对象操作(选取、排除、合并、克隆、分组)
- 集合操作(并集、交集、差集)
- 无需外部库的深度克隆
- 函数工具(防抖、节流、记忆化)
不适用场景:
- 带自定义数组处理策略的复杂深度合并——使用库
- 大型数据集上的惰性求值链式调用——lodash链式调用针对此场景做了优化
- 需要克隆包含函数的对象——无法克隆函数
structuredClone - 具备取消、刷新、前导/尾随触发的全功能防抖/节流——使用库
涵盖的核心模式:
- 安全属性访问(可选链+空值合并替代)
_.get - 不可变数组操作(、
toSorted、toReversed、toSpliced)with - 使用进行深度克隆(支持Map、Set、Date、循环引用)
structuredClone - /
Object.groupBy(ES2024——替代基于reduce的分组)Map.groupBy - ES2025 Set方法(并集、交集、差集、对称差集)
- 对象选取/排除、去重、分块、扁平化
详细资源:
- examples/core.md - 安全访问、深度克隆、不可变数组、findLast
- examples/arrays.md - 去重、集合操作、分组、分块、排序
- examples/objects.md - 选取、排除、合并、mapKeys/mapValues、冻结
- reference.md - 决策框架、lodash转原生对照表、警示信号、反模式
<philosophy>
Philosophy
理念
Modern JavaScript (ES2022-ES2025) provides native alternatives for ~80% of common utility library functions. Using native methods means:
- Zero bundle cost - No additional bytes shipped to users
- Better performance - Native implementations are engine-optimized
- Future-proof - Standards evolve, libraries may not
- Simpler debugging - No library internals to step through
Key principle: Check native JavaScript first. Only use utility libraries for genuinely missing functionality.
typescript
// Native is free - no imports needed
const unique = [...new Set(items)];
const last = items.at(-1);
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name));
const cloned = structuredClone(complexObject);
const grouped = Object.groupBy(items, (item) => item.category);ES Version Reference:
| Feature | ES Version | Browser Support |
|---|---|---|
Optional chaining ( | ES2020 | All modern browsers |
Nullish coalescing ( | ES2020 | All modern browsers |
| ES2022 | All modern browsers |
| ES2023 | All modern browsers |
| ES2024 | Chrome 117+, Safari 17.4+ |
| Set methods (union, etc.) | ES2025 | Chrome 122+, Safari 17+ |
<patterns>
现代JavaScript(ES2022-ES2025)为约80%的常见工具库函数提供了原生替代方案。使用原生方法意味着:
- 零打包成本 - 无需向用户额外发送代码字节
- 更佳性能 - 原生实现经过引擎优化
- 面向未来 - 标准会演进,而库可能不会
- 调试更简单 - 无需深入库的内部代码
**核心原则:**先检查原生JavaScript。仅在功能确实缺失时才使用工具库。
typescript
// 原生方法无需导入,零成本
const unique = [...new Set(items)];
const last = items.at(-1);
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name));
const cloned = structuredClone(complexObject);
const grouped = Object.groupBy(items, (item) => item.category);ES版本参考:
| 特性 | ES版本 | 浏览器支持 |
|---|---|---|
可选链( | ES2020 | 所有现代浏览器 |
空值合并( | ES2020 | 所有现代浏览器 |
| ES2022 | 所有现代浏览器 |
| ES2023 | 所有现代浏览器 |
| ES2024 | Chrome 117+, Safari 17.4+ |
| Set方法(并集等) | ES2025 | Chrome 122+, Safari 17+ |
<patterns>
Core Patterns
核心模式
Pattern 1: Safe Property Access
模式1:安全属性访问
Optional chaining + nullish coalescing replaces with zero bundle cost.
_.gettypescript
const DEFAULT_CITY = "Unknown";
const city = user?.address?.city ?? DEFAULT_CITY;
const result = service?.logger?.log?.("message"); // method call
const first = data?.items?.[0]?.name ?? "No items"; // array accessWhy this matters: Handles null/undefined gracefully, type-safe with TypeScript, no runtime cost.
See examples/core.md for full patterns.
可选链+空值合并可零成本替代。
_.gettypescript
const DEFAULT_CITY = "Unknown";
const city = user?.address?.city ?? DEFAULT_CITY;
const result = service?.logger?.log?.("message"); // 方法调用
const first = data?.items?.[0]?.name ?? "No items"; // 数组访问**重要性:**优雅处理null/undefined,在TypeScript中类型安全,无运行时成本。
查看examples/core.md获取完整模式。
Pattern 2: Immutable Array Operations (ES2023)
模式2:不可变数组操作(ES2023)
Always use immutable variants - critical for reactive frameworks and shared state.
typescript
const sorted = items.toSorted((a, b) => a.price - b.price); // not .sort()
const reversed = items.toReversed(); // not .reverse()
const updated = items.with(1, newItem); // not items[1] = x
const removed = items.toSpliced(1, 1); // not .splice()Why this matters: Mutating methods cause bugs in shared state and reactive frameworks that rely on reference equality to detect changes.
See examples/core.md for immutable update patterns.
始终使用不可变变体——这对响应式框架和共享状态至关重要。
typescript
const sorted = items.toSorted((a, b) => a.price - b.price); // 不要用.sort()
const reversed = items.toReversed(); // 不要用.reverse()
const updated = items.with(1, newItem); // 不要用items[1] = x
const removed = items.toSpliced(1, 1); // 不要用.splice()**重要性:**可变方法会在共享状态和依赖引用相等性检测变化的响应式框架中引发bug。
查看examples/core.md获取不可变更新模式。
Pattern 3: Deep Cloning with structuredClone
模式3:使用structuredClone进行深度克隆
Replaces JSON round-trip and lodash . Handles types JSON cannot.
_.cloneDeeptypescript
const cloned = structuredClone(complexObject);
// Preserves: Date, Map, Set, RegExp, ArrayBuffer, circular references
// Cannot clone: functions, DOM nodes, Error objects with custom propertiesWhy this matters: silently corrupts Date (becomes string), Map/Set (becomes ), and loses .
JSON.parse(JSON.stringify()){}undefinedSee examples/core.md for cloning patterns.
替代JSON往返和lodash的。支持JSON无法处理的类型。
_.cloneDeeptypescript
const cloned = structuredClone(complexObject);
// 保留:Date、Map、Set、RegExp、ArrayBuffer、循环引用
// 无法克隆:函数、DOM节点、带自定义属性的Error对象重要性:会静默破坏Date(变为字符串)、Map/Set(变为),并丢失。
JSON.parse(JSON.stringify()){}undefined查看examples/core.md获取克隆模式。
Pattern 4: Object.groupBy (ES2024)
模式4:Object.groupBy(ES2024)
Replaces verbose reduce-based grouping and lodash .
_.groupBytypescript
const byCategory = Object.groupBy(products, (p) => p.category);
const THRESHOLD = 100;
const byRange = Object.groupBy(items, (item) =>
item.price >= THRESHOLD ? "expensive" : "affordable",
);
// Returns null-prototype object - use Object.hasOwn() not hasOwnPropertyWhy this matters: Reduce-based grouping is verbose, error-prone (forgetting key init), and has prototype pollution risk with .
{}See examples/arrays.md for grouping patterns.
替代冗长的基于reduce的分组和lodash的。
_.groupBytypescript
const byCategory = Object.groupBy(products, (p) => p.category);
const THRESHOLD = 100;
const byRange = Object.groupBy(items, (item) =>
item.price >= THRESHOLD ? "expensive" : "affordable",
);
// 返回无原型对象——使用Object.hasOwn()而非hasOwnProperty**重要性:**基于reduce的分组冗长、易出错(忘记初始化键),且使用存在原型污染风险。
{}查看examples/arrays.md获取分组模式。
Pattern 5: ES2025 Set Methods
模式5:ES2025 Set方法
Native set operations replace manual filter-based implementations.
typescript
const union = setA.union(setB);
const common = setA.intersection(setB);
const diff = setA.difference(setB);
const either = setA.symmetricDifference(setB);
const isSub = setA.isSubsetOf(setB);
// Returns Set - spread to array if needed: [...setA.union(setB)]Why this matters: Filter + includes/indexOf is O(n^2). Native Set methods are O(n).
See examples/arrays.md for set operations and pre-ES2025 fallbacks.
原生集合操作替代手动基于filter的实现。
typescript
const union = setA.union(setB);
const common = setA.intersection(setB);
const diff = setA.difference(setB);
const either = setA.symmetricDifference(setB);
const isSub = setA.isSubsetOf(setB);
// 返回Set——如需数组则展开:[...setA.union(setB)]**重要性:**Filter + includes/indexOf的时间复杂度为O(n²)。原生Set方法为O(n)。
查看examples/arrays.md获取集合操作和ES2025之前的回退方案。
Pattern 6: Finding from End (ES2023)
模式6:从末尾查找(ES2023)
findLastfindLastIndextypescript
const lastError = logs.findLast((log) => log.level === "error");
const lastErrorIdx = logs.findLastIndex((log) => log.level === "error");Why this matters: creates unnecessary copy. is single-pass.
[...arr].reverse().find()findLastSee examples/core.md for findLast patterns.
</patterns>
<red_flags>
findLastfindLastIndextypescript
const lastError = logs.findLast((log) => log.level === "error");
const lastErrorIdx = logs.findLastIndex((log) => log.level === "error");重要性:会创建不必要的副本。是单次遍历。
[...arr].reverse().find()findLast查看examples/core.md获取findLast模式。
</patterns>
<red_flags>
RED FLAGS
警示信号
High Priority:
- Using for deep clone - loses Date, Map, Set, undefined. Use
JSON.parse(JSON.stringify()).structuredClone - Using mutating array methods (,
.sort(),.reverse()) on shared state - causes bugs in reactive frameworks. Use ES2023 immutable versions..splice() - Using lodash for operations with native equivalents (,
_.get,_.last,_.uniq) - unnecessary bundle weight._.groupBy - Using or
includes()in loops - O(n) per check. Convert to Set first for O(1) lookups.indexOf()
Medium Priority:
- Magic numbers like - use named constants:
arr.slice(-3).const RECENT_COUNT = 3 - Reversing arrays to find from end - use instead of
findLast().[...arr].reverse().find() - Reduce-based grouping - use (ES2024).
Object.groupBy() - Using for last element - use
arr[arr.length - 1].arr.at(-1)
Gotchas & Edge Cases:
- throws on functions, DOM nodes - use manual clone if these are present.
structuredClone - returns null-prototype object - no
Object.groupBy. UsehasOwnProperty.Object.hasOwn() - Set methods return Sets, not arrays - spread to array if needed: .
[...setA.union(setB)] - with no comparator converts elements to strings (like
toSorted()).sort() - returns
at()for empty arrays or out-of-bounds indices.undefined
</red_flags>
<critical_reminders>
高优先级:
- 使用进行深度克隆——丢失Date、Map、Set、undefined。请使用
JSON.parse(JSON.stringify())。structuredClone - 在共享状态上使用可变数组方法(、
.sort()、.reverse())——会在响应式框架中引发bug。请使用ES2023不可变版本。.splice() - 使用lodash实现已有原生等价方案的操作(、
_.get、_.last、_.uniq)——造成不必要的打包体积。_.groupBy - 在循环中使用或
includes()——每次检查的时间复杂度为O(n)。先转换为Set以实现O(1)查找。indexOf()
中优先级:
- 魔法数字如——使用命名常量:
arr.slice(-3)。const RECENT_COUNT = 3 - 反转数组以从末尾查找——使用替代
findLast()。[...arr].reverse().find() - 基于reduce的分组——使用(ES2024)。
Object.groupBy() - 使用获取最后一个元素——使用
arr[arr.length - 1]。arr.at(-1)
陷阱与边缘情况:
- 在遇到函数、DOM节点时会抛出错误——若存在这些类型,请手动克隆。
structuredClone - 返回无原型对象——没有
Object.groupBy。请使用hasOwnProperty。Object.hasOwn() - Set方法返回Set而非数组——如需数组则展开:。
[...setA.union(setB)] - 不带比较器的会将元素转换为字符串(类似
toSorted())。sort() - 对于空数组或越界索引,返回
at()。undefined
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
重要提醒
All code must follow project conventions in CLAUDE.md
(You MUST use native ES2022+ methods before considering utility libraries - check this skill first)
(You MUST use immutable array methods (, , , ) instead of mutating methods)
toSortedtoReversedtoSplicedwith(You MUST use for deep cloning - NOT JSON.parse/JSON.stringify hacks)
structuredClone(You MUST define named constants for all numeric values - NO magic numbers in utility functions)
Failure to follow these rules will cause unnecessary bundle bloat and mutation bugs.
</critical_reminders>
所有代码必须遵循CLAUDE.md中的项目约定
(在考虑使用工具库之前,必须优先使用原生ES2022+方法——先查阅本技能)
(必须使用不可变数组方法(、、、)而非可变方法)
toSortedtoReversedtoSplicedwith(必须使用进行深度克隆——禁止使用JSON.parse/JSON.stringify这类取巧方式)
structuredClone(必须为所有数值定义命名常量——工具函数中禁止使用魔法数字)
不遵守这些规则会导致不必要的打包体积膨胀和可变bug。
</critical_reminders>