A decorator augments method behavior without changing the method’s core implementation. It separates cross-cutting concerns—such as validation, logging, tracing, and performance measurement—from business logic by intercepting calls and running behavior before and after the target method. section 7.7 section 1.4
A decorator specification can describe:
- before behavior that preprocesses method arguments, such as validating a positive integer; section 7.7
- after behavior that postprocesses a method’s return value, with the identity function providing pass-through behavior; section 7.7
- a method list identifying which methods receive the decoration. section 7.7
Validating a Counter
The validation decorator applies checkLimit before Counter methods inc and dec, then passes the result through unchanged. A proxy intercepts access to those methods, returns a higher-order wrapper, captures the call arguments, runs the before action, invokes the original method, and applies the after action. Thus counter$Proxy.inc() returns 4, counter$Proxy.inc(3) returns 7, and counter$Proxy.inc(-3) throws a RangeError. section 7.7
Listing 7.37 Main logic that applies a decorator to a proxy object
const decorate = (decorator, obj) => new Proxy(obj, {
get(target, key) {
if (!decorator.methods.includes(key)) {
return Reflect.get(...arguments);
}
const methodRef = target[key]; #1
return (...capturedArgs) => { #2
const newArgs = #3
decorator.actions?.before.call(target, ...capturedArgs);
const result = methodRef.call(target, ...[newArgs]); #4
return decorator.actions?.after.call(target, result) ; #5
};
}
})
Inspect the proxy-based implementation that preserves ordinary property access while wrapping only methods named by the decorator. section 7.7






