liveBook · Manning

Decorator

As explained in The Joy of JavaScript

A wrapper-like construct that augments method behavior without changing the method's core implementation.

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

How The Joy of JavaScript covers it

How deep it goes
Explains object specifications, before-and-after actions, higher-order wrappers, and Proxy/Reflect wiring, but not decorator syntax.
Examples
Demonstrates Counter validation, credential tracing, password obfuscation, and composition of nested proxies.
What it assumes
Assumes familiarity with objects, functions, higher-order functions, and identity functions while introducing Proxy and Reflect for interception.
What you can do after
Apply validation, tracing, logging, or return-value enhancement without modifying the decorated object’s business methods.
How it connects
Connects decorators to metaprogramming, Proxy, Reflect, higher-order functions, identity functions, and separation of concerns.

Also explained in

Compare how 7 books explain decorator →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.