Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Web Utilities Native Js

ASecurity

Modern native JavaScript (ES2022-ES2025) utility patterns that replace lodash

24 stars
0 votes
0 copies
1 views
Added 5/29/2026
ai-agentsjavascripttypescriptrustjavareactnode

Security Analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned 9/21/2026

$npx -y skills add agents-inc/skills --skill web-utilities-native-js --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Web Utilities Native Js?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Web Utilities Native Js
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/agents-inc-web-utilities-native-js/badge)](https://www.skillsdirectory.com/skills/agents-inc-web-utilities-native-js)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: web-utilities-native-js
description: Modern native JavaScript (ES2022-ES2025) utility patterns that replace lodash
---

# Native JavaScript Utility Patterns

> **Quick Guide:** Most utility-library calls now have a native equivalent with no bundle cost.
> The four that change how code is written are `structuredClone` for deep copies, the ES2023
> immutable array methods (`toSorted`, `toReversed`, `toSpliced`, `with`), `Object.groupBy` /
> `Map.groupBy`, and the ES2025 Set operations. The two facts that catch people out: a structured
> clone drops prototypes and throws on functions, and the immutable array methods copy one level
> deep.

**Detailed Resources:**

- [examples/core.md](examples/core.md) — cloning, immutable updates, negative indexing, searching from the end
- [examples/arrays.md](examples/arrays.md) — deduplication, set operations, grouping, chunking, sorting, compacting
- [examples/objects.md](examples/objects.md) — typed pick/omit/mapValues, deep merge, lookup maps, freezing
- [reference.md](reference.md) — lodash-to-native table, function utilities (debounce, throttle, memoize), availability

---

<critical_requirements>

## Before writing utility code

**Reach for the native method before adding a dependency.** The lodash-to-native table in
[reference.md](reference.md) settles most of it in one lookup, and the native call ships nothing.

**Deep-copy with `structuredClone`.** A JSON round trip turns a `Date` into a string and a `Map` or
`Set` into `{}`, and it does so silently — the failure surfaces later, at the first `.getTime()`.

**Use the `to*` array methods where the array is shared.** `sort`, `reverse` and `splice` rewrite
the array in place, so a function that "returns a sorted copy" with `sort` has changed its caller's
data.

**Convert to a `Set` before repeated membership checks.** `includes` inside a `filter` is O(n²), and
the difference shows up at a few thousand elements.

</critical_requirements>

---

**Auto-detection:** structuredClone, Object.groupBy, Map.groupBy, toSorted, toReversed, toSpliced,
Array.prototype.with, findLast, findLastIndex, at(-1), Object.hasOwn, Object.fromEntries,
Set.prototype.union, Set.prototype.intersection, Set.prototype.difference, symmetricDifference,
isSubsetOf, isDisjointFrom, lodash alternative, native JavaScript utilities

**Applies to:**

- Array work — deduplicating, grouping, chunking, flattening, sorting immutably, searching from the end
- Object work — picking, omitting, merging, key/value transformation, lookup maps
- Set algebra — union, intersection, difference, subset tests
- Deep copying without a dependency
- Hand-rolled function utilities — debounce, throttle, memoize, once

**Handled elsewhere:**

- Date arithmetic, parsing and formatting — `Date` alone does not cover it
- Reactive updates — these methods produce new references, and what consumes a new reference is the concern of whatever owns the state
- Schema validation and runtime parsing — these utilities reshape data that is already trusted

---

<decision_framework>

## Native or a dependency

Three cases, in order:

- **A native method exists** — use it. The table in [reference.md](reference.md) is the lookup.
- **No native method, but the implementation is ten lines** — write it. `chunk`, `pick`, `omit`,
  `compact`, `deepMerge`, `debounce`, `throttle`, `memoize` and `once` are all in this skill,
  written out and typed.
- **The edge cases are the feature** — take the dependency. A debounce with `cancel`, `flush` and
  leading/trailing edges; a deep merge with per-key array strategies; lazy evaluation over a
  dataset large enough that intermediate arrays matter. Reimplementing these badly costs more than
  the bytes.

</decision_framework>

---

<patterns>

## Core patterns

### Pattern 1: structuredClone for deep copies

Preserves `Date`, `Map`, `Set`, `RegExp`, typed arrays and circular references — everything a JSON
round trip destroys.

```typescript
const snapshot = structuredClone(state);
// Preserved: Date, Map, Set, RegExp, ArrayBuffer, circular refs
// Throws on: functions, DOM nodes, Proxy, symbols
// Silently lost: the prototype — a class instance clones to a plain object
```

Full code: [examples/core.md](examples/core.md)

---

### Pattern 2: Immutable array methods (ES2023)

Four `to*` methods return a new array where the classic method rewrote the old one.

```typescript
items.toSorted((a, b) => a.price - b.price); // vs .sort()
items.toReversed(); // vs .reverse()
items.toSpliced(index, 1); // vs .splice()
items.with(index, { ...items[index], done: true }); // vs items[i] = x
```

The copy is shallow: the new array holds the same element objects, which is why the update above
spreads before writing.

Full code: [examples/core.md](examples/core.md)

---

### Pattern 3: Object.groupBy and Map.groupBy (ES2024)

```typescript
const byStatus = Object.groupBy(orders, (order) => order.status);
// { pending: [...], shipped: [...] } — null-prototype, values are `T[] | undefined`

const byCustomer = Map.groupBy(orders, (order) => order.customer);
// Map keyed by the object itself — use this when the key is not a string
```

`Object.groupBy` coerces the key to a string and returns a null-prototype object, so reach for
`Object.hasOwn(byStatus, key)` rather than `byStatus.hasOwnProperty(key)`.

Full code: [examples/arrays.md](examples/arrays.md)

---

### Pattern 4: Set operations (ES2025)

```typescript
setA.union(setB);
setA.intersection(setB);
setA.difference(setB); // in A, not in B
setA.symmetricDifference(setB);
setA.isSubsetOf(setB);
setA.isSupersetOf(setB);
setA.isDisjointFrom(setB);
```

Each returns a `Set`, so spread when an array is wanted. The argument is any set-like with `size`,
`has` and `keys` — a `Map` qualifies, a plain array does not.

Full code: [examples/arrays.md](examples/arrays.md)

---

### Pattern 5: Searching and indexing from the end

```typescript
logs.findLast((log) => log.level === "error"); // ES2023, single pass
logs.findLastIndex((log) => log.level === "error");
items.at(-1); // ES2022, undefined when empty
"file.backup.txt".split(".").at(-1); // "txt" — strings too
```

Full code: [examples/core.md](examples/core.md)

---

### Pattern 6: Object.fromEntries as the transformation pivot

`entries → map/filter → fromEntries` covers pick, omit, invert, mapValues, mapKeys and array-to-lookup
in one shape, so those helpers are four lines each rather than a dependency.

```typescript
const keyed = Object.fromEntries(items.map((item) => [item.id, item]));
const withTax = Object.fromEntries(
  Object.entries(prices).map(([k, v]) => [k, v * 1.1]),
);
const passing = Object.fromEntries(
  Object.entries(scores).filter(([, score]) => score >= 90),
);
```

Full code: [examples/objects.md](examples/objects.md)

</patterns>

---

<red_flags>

## Red flags

**Breaks at runtime:**

- `structuredClone` on anything holding a function, a DOM node or a Proxy throws `DataCloneError` — clone the data separately from the behaviour.
- `JSON.parse(JSON.stringify(x))` does not throw; it corrupts. A `Date` becomes a string, a `Map` or `Set` becomes `{}`, `undefined` members vanish, and the first method call on the result is where it surfaces.
- `Object.groupBy` returns a null-prototype object, so `result.hasOwnProperty(...)` throws. Use `Object.hasOwn`.
- Set methods reject a plain array — they need something with `size`, `has` and `keys`.

**Surprising behaviour:**

- `structuredClone` discards the prototype. A class instance clones to a plain object with the same fields and none of the methods.
- `toSorted()` with no comparator sorts by string, so `[10, 9, 1].toSorted()` is `[1, 10, 9]` — exactly as `sort()` always did.
- The `to*` methods copy one level. Editing an element of the new array edits the same object in the old one.
- `arr.at(-1)` types as `T | undefined` whatever the compiler options, so the empty case has to be handled. `arr[arr.length - 1]` types as `T` unless `noUncheckedIndexedAccess` is on — that is the form that lets an `undefined` flow on unchecked.
- `structuredClone` on an `Error` succeeds and keeps the standard fields, but a `code`, a `status` or anything else attached to it is not in the copy.
- `filter(Boolean)` drops `0`, `""` and `false` along with the nullish values, and TypeScript does not narrow the result — `filter((x): x is T => x != null)` does both jobs correctly.
- `Object.freeze` is shallow, and outside strict mode a write to a frozen object fails silently rather than throwing.
- `Object.keys` returns integer-like keys first in ascending numeric order, whatever the insertion order — only string keys keep insertion order.

</red_flags>

Attribution

agents-incagents-inc
View sourceSee grades on GitHubMore from agents-inc →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698461 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →