install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/js-proxy-pattern" ~/.claude/skills/intense-visions-harness-engineering-js-proxy-pattern && rm -rf "$T"
manifest:
agents/skills/claude-code/js-proxy-pattern/SKILL.mdsource content
JS Proxy Pattern
Intercept and control object property access with ES6 Proxy
When to Use
- You need to validate, log, or transform property reads/writes without changing the target object
- Implementing reactive data systems (watching object mutations)
- Adding access control or lazy initialization to expensive objects
- Building observable models for state management
Instructions
- Create a handler object with trap methods (
,get
,set
, etc.).deleteProperty - Wrap the target object:
.const proxy = new Proxy(target, handler) - In
traps, always callset
to apply the change and return its boolean result.Reflect.set(target, prop, value) - In
traps, useget
to preserve prototype chain behavior.Reflect.get(target, prop, receiver) - Use
methods in traps — they mirror the Proxy trap API and ensure correct semantics.Reflect
const validator = { set(target, prop, value) { if (prop === 'age') { if (typeof value !== 'number' || value < 0) { throw new TypeError('Age must be a non-negative number'); } } return Reflect.set(target, prop, value); }, }; const person = new Proxy({}, validator); person.age = 30; // OK person.age = -1; // Throws TypeError
- Avoid deeply nested Proxy wrapping — it compounds performance overhead on every property access.
Details
ES6
Proxy gives you a meta-programming hook at the object level. Traps intercept fundamental operations: get, set, has, deleteProperty, apply (for functions), and construct (for classes).
Trade-offs:
- Proxy adds overhead per property access — avoid on hot paths (tight loops, rendering cycles)
- Proxied objects are not equal to their targets (
) — equality checks must use the targetproxy !== target - Proxies are not serializable —
serializes the underlying target, which may surprise callersJSON.stringify(proxy) - Debugging is harder — the DevTools shows the proxy wrapper, not the target directly
When NOT to use:
- For simple validation — just write a setter method or use a class
- For immutability at scale —
is simpler and has no runtime overhead per accessObject.freeze() - When you need ES5 compatibility — Proxy cannot be polyfilled
Related patterns:
- Observer Pattern — Proxy can power reactive observation of object mutations
- Singleton Pattern — a Proxy can wrap a singleton to control access
Source
https://patterns.dev/javascript/proxy-pattern
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.