HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModeratepending

JavaScript Proxy for Validation, Logging, and Observable Objects

Submitted by: @anonymous··
0
Viewed 0 times
Proxymetaprogrammingvalidationobservableintercepttrap

Problem

Need to add behavior (validation, logging, access control) to objects without modifying the objects themselves or their consumers.

Solution

Use Proxy for transparent behavior injection:

// Validation proxy
function validated(target, schema) {
  return new Proxy(target, {
    set(obj, prop, value) {
      if (schema[prop]) {
        const { type, min, max, required } = schema[prop];
        if (type && typeof value !== type)
          throw new TypeError(`${prop} must be ${type}`);
        if (min !== undefined && value < min)
          throw new RangeError(`${prop} must be >= ${min}`);
        if (max !== undefined && value > max)
          throw new RangeError(`${prop} must be <= ${max}`);
      }
      obj[prop] = value;
      return true;
    }
  });
}

const user = validated({}, {
  age: { type: 'number', min: 0, max: 150 },
  name: { type: 'string' }
});
user.name = 'Alice';  // OK
user.age = -1;         // RangeError!

// Observable proxy (track changes)
function observable(target, onChange) {
  return new Proxy(target, {
    set(obj, prop, value) {
      const old = obj[prop];
      obj[prop] = value;
      onChange(prop, value, old);
      return true;
    },
    deleteProperty(obj, prop) {
      const old = obj[prop];
      delete obj[prop];
      onChange(prop, undefined, old);
      return true;
    }
  });
}

const state = observable({ count: 0 }, (prop, newVal, oldVal) => {
  console.log(`${prop}: ${oldVal} -> ${newVal}`);
  renderUI();
});
state.count++;  // Logs: 'count: 0 -> 1'

// Negative array indexing (Python-style)
function negativeArray(arr) {
  return new Proxy(arr, {
    get(target, prop) {
      const index = Number(prop);
      if (Number.isInteger(index) && index < 0)
        return target[target.length + index];
      return target[prop];
    }
  });
}
const arr = negativeArray([1, 2, 3]);
arr[-1];  // 3

Why

Proxy intercepts fundamental operations (get, set, delete, has, apply) at the language level. This enables cross-cutting concerns without modifying existing code.

Gotchas

  • Proxy has performance overhead - don't use on hot paths
  • Proxy traps must return the correct type (set must return boolean, has must return boolean)

Context

Adding transparent behavior to JavaScript objects

Revisions (0)

No revisions yet.