web-utilities-native-js

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Native JavaScript Utility Patterns

原生JavaScript实用工具模式

Quick Guide: Prefer native JavaScript (ES2022-ES2025) over utility libraries. Use
structuredClone
for deep cloning,
Object.groupBy
for grouping, ES2023 immutable array methods (
toSorted
,
toReversed
,
with
), 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).

<critical_requirements>
**快速指南:**优先使用原生JavaScript(ES2022-ES2025)而非工具库。使用
structuredClone
进行深度克隆,使用
Object.groupBy
进行分组,使用ES2023不可变数组方法(
toSorted
toReversed
with
),以及ES2025 Set方法进行集合操作。仅当原生替代方案确实不存在或缺少所需功能(如防抖的取消/刷新、带数组策略的深度合并)时,才考虑使用工具库。

<critical_requirements>

CRITICAL: Before Using This Skill

重要提示:使用本技能之前

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type
, named constants)
(You MUST use native ES2022+ methods before considering utility libraries - check this skill first)
(You MUST use immutable array methods (
toSorted
,
toReversed
,
toSpliced
,
with
) instead of mutating methods)
(You MUST use
structuredClone
for deep cloning - NOT JSON.parse/JSON.stringify hacks)
(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 -
    structuredClone
    cannot clone functions
  • 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
    structuredClone
    (handles Map, Set, Date, circular refs)
  • Object.groupBy
    /
    Map.groupBy
    (ES2024 - replaces reduce-based grouping)
  • 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+方法——先查阅本技能)
(必须使用不可变数组方法(
toSorted
toReversed
toSpliced
with
)而非可变方法)
(必须使用
structuredClone
进行深度克隆——禁止使用JSON.parse/JSON.stringify这类取巧方式)
(必须为所有数值定义命名常量——工具函数中禁止使用魔法数字)
</critical_requirements>

**自动检测:**原生JavaScript工具、lodash替代方案、ES2023数组方法、toSorted、toReversed、structuredClone、Object.groupBy、Set并集、Set交集、可选链、空值合并、at()、findLast
适用场景:
  • 数组操作(查找、过滤、排序、反转、分块、去重、分组)
  • 对象操作(选取、排除、合并、克隆、分组)
  • 集合操作(并集、交集、差集)
  • 无需外部库的深度克隆
  • 函数工具(防抖、节流、记忆化)
不适用场景:
  • 带自定义数组处理策略的复杂深度合并——使用库
  • 大型数据集上的惰性求值链式调用——lodash链式调用针对此场景做了优化
  • 需要克隆包含函数的对象——
    structuredClone
    无法克隆函数
  • 具备取消、刷新、前导/尾随触发的全功能防抖/节流——使用库
涵盖的核心模式:
  • 安全属性访问(可选链+空值合并替代
    _.get
  • 不可变数组操作(
    toSorted
    toReversed
    toSpliced
    with
  • 使用
    structuredClone
    进行深度克隆(支持Map、Set、Date、循环引用)
  • Object.groupBy
    /
    Map.groupBy
    (ES2024——替代基于reduce的分组)
  • 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:
  1. Zero bundle cost - No additional bytes shipped to users
  2. Better performance - Native implementations are engine-optimized
  3. Future-proof - Standards evolve, libraries may not
  4. 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:
FeatureES VersionBrowser Support
Optional chaining (
?.
)
ES2020All modern browsers
Nullish coalescing (
??
)
ES2020All modern browsers
at()
negative indexing
ES2022All modern browsers
toSorted
,
toReversed
,
with
ES2023All modern browsers
Object.groupBy
,
Map.groupBy
ES2024Chrome 117+, Safari 17.4+
Set methods (union, etc.)ES2025Chrome 122+, Safari 17+
</philosophy>
<patterns>
现代JavaScript(ES2022-ES2025)为约80%的常见工具库函数提供了原生替代方案。使用原生方法意味着:
  1. 零打包成本 - 无需向用户额外发送代码字节
  2. 更佳性能 - 原生实现经过引擎优化
  3. 面向未来 - 标准会演进,而库可能不会
  4. 调试更简单 - 无需深入库的内部代码
**核心原则:**先检查原生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所有现代浏览器
at()
负索引
ES2022所有现代浏览器
toSorted
toReversed
with
ES2023所有现代浏览器
Object.groupBy
Map.groupBy
ES2024Chrome 117+, Safari 17.4+
Set方法(并集等)ES2025Chrome 122+, Safari 17+
</philosophy>
<patterns>

Core Patterns

核心模式

Pattern 1: Safe Property Access

模式1:安全属性访问

Optional chaining + nullish coalescing replaces
_.get
with zero bundle cost.
typescript
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 access
Why this matters: Handles null/undefined gracefully, type-safe with TypeScript, no runtime cost.
See examples/core.md for full patterns.

可选链+空值合并可零成本替代
_.get
typescript
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
_.cloneDeep
. Handles types JSON cannot.
typescript
const cloned = structuredClone(complexObject);
// Preserves: Date, Map, Set, RegExp, ArrayBuffer, circular references
// Cannot clone: functions, DOM nodes, Error objects with custom properties
Why this matters:
JSON.parse(JSON.stringify())
silently corrupts Date (becomes string), Map/Set (becomes
{}
), and loses
undefined
.
See examples/core.md for cloning patterns.

替代JSON往返和lodash的
_.cloneDeep
。支持JSON无法处理的类型。
typescript
const cloned = structuredClone(complexObject);
// 保留:Date、Map、Set、RegExp、ArrayBuffer、循环引用
// 无法克隆:函数、DOM节点、带自定义属性的Error对象
重要性:
JSON.parse(JSON.stringify())
会静默破坏Date(变为字符串)、Map/Set(变为
{}
),并丢失
undefined
查看examples/core.md获取克隆模式。

Pattern 4: Object.groupBy (ES2024)

模式4:Object.groupBy(ES2024)

Replaces verbose reduce-based grouping and lodash
_.groupBy
.
typescript
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 hasOwnProperty
Why 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的
_.groupBy
typescript
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)

findLast
and
findLastIndex
replace reverse-then-find anti-pattern.
typescript
const lastError = logs.findLast((log) => log.level === "error");
const lastErrorIdx = logs.findLastIndex((log) => log.level === "error");
Why this matters:
[...arr].reverse().find()
creates unnecessary copy.
findLast
is single-pass.
See examples/core.md for findLast patterns.
</patterns>
<red_flags>
findLast
findLastIndex
替代“反转后查找”的反模式。
typescript
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
    JSON.parse(JSON.stringify())
    for deep clone - loses Date, Map, Set, undefined. Use
    structuredClone
    .
  • Using mutating array methods (
    .sort()
    ,
    .reverse()
    ,
    .splice()
    ) on shared state - causes bugs in reactive frameworks. Use ES2023 immutable versions.
  • Using lodash for operations with native equivalents (
    _.get
    ,
    _.last
    ,
    _.uniq
    ,
    _.groupBy
    ) - unnecessary bundle weight.
  • Using
    includes()
    or
    indexOf()
    in loops - O(n) per check. Convert to Set first for O(1) lookups.
Medium Priority:
  • Magic numbers like
    arr.slice(-3)
    - use named constants:
    const RECENT_COUNT = 3
    .
  • Reversing arrays to find from end - use
    findLast()
    instead of
    [...arr].reverse().find()
    .
  • Reduce-based grouping - use
    Object.groupBy()
    (ES2024).
  • Using
    arr[arr.length - 1]
    for last element - use
    arr.at(-1)
    .
Gotchas & Edge Cases:
  • structuredClone
    throws on functions, DOM nodes - use manual clone if these are present.
  • Object.groupBy
    returns null-prototype object - no
    hasOwnProperty
    . Use
    Object.hasOwn()
    .
  • Set methods return Sets, not arrays - spread to array if needed:
    [...setA.union(setB)]
    .
  • toSorted()
    with no comparator converts elements to strings (like
    sort()
    ).
  • at()
    returns
    undefined
    for empty arrays or out-of-bounds indices.
</red_flags>

<critical_reminders>
高优先级:
  • 使用
    JSON.parse(JSON.stringify())
    进行深度克隆——丢失Date、Map、Set、undefined。请使用
    structuredClone
  • 在共享状态上使用可变数组方法(
    .sort()
    .reverse()
    .splice()
    )——会在响应式框架中引发bug。请使用ES2023不可变版本。
  • 使用lodash实现已有原生等价方案的操作(
    _.get
    _.last
    _.uniq
    _.groupBy
    )——造成不必要的打包体积。
  • 在循环中使用
    includes()
    indexOf()
    ——每次检查的时间复杂度为O(n)。先转换为Set以实现O(1)查找。
中优先级:
  • 魔法数字如
    arr.slice(-3)
    ——使用命名常量:
    const RECENT_COUNT = 3
  • 反转数组以从末尾查找——使用
    findLast()
    替代
    [...arr].reverse().find()
  • 基于reduce的分组——使用
    Object.groupBy()
    (ES2024)。
  • 使用
    arr[arr.length - 1]
    获取最后一个元素——使用
    arr.at(-1)
陷阱与边缘情况:
  • structuredClone
    在遇到函数、DOM节点时会抛出错误——若存在这些类型,请手动克隆。
  • 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 (
toSorted
,
toReversed
,
toSpliced
,
with
) instead of mutating methods)
(You MUST use
structuredClone
for deep cloning - NOT JSON.parse/JSON.stringify hacks)
(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+方法——先查阅本技能)
(必须使用不可变数组方法(
toSorted
toReversed
toSpliced
with
)而非可变方法)
(必须使用
structuredClone
进行深度克隆——禁止使用JSON.parse/JSON.stringify这类取巧方式)
(必须为所有数值定义命名常量——工具函数中禁止使用魔法数字)
不遵守这些规则会导致不必要的打包体积膨胀和可变bug。
</critical_reminders>