CodeBlanks Logo Icon CodeBlanks

Summary - Metaprogramming

JavaScript course · Expert · Lesson 41/63

Build a logging wrapper with Proxy, Reflect and the decorator pattern.

Summary - Metaprogramming

In this group you saw four techniques. With reflection you read an object's structure; with Proxy you validated assignments; with Reflect you applied default behavior inside a trap; with Symbol.iterator you made objects traversable; and with the decorator pattern you wrapped functions.

The common thread: code manages another code's structure or behavior. A behavior defined in one place applies to every assignment, call or loop.

In the last step we will combine these into a logging wrapper.

Combine the techniques

A logging wrapper combines Proxy, Reflect and the decorator idea. The goal: watch every read and write on an object.

The approach: function withLog(target) defines a handler; the get trap runs console.log('get', prop) then return Reflect.get(target, prop, receiver); the set trap similarly logs and applies Reflect.set. Then return new Proxy(target, handler).

This single function turns any object into a transparently observed one.

Exercise Build a logging wrapper

Define a function withLog(target). Inside it, define a handler object; the get(target, prop, receiver) trap logs console.log('get', prop) then return Reflect.get(target, prop, receiver); the set(target, prop, value, receiver) trap logs console.log('set', prop, value) then return Reflect.set(target, prop, value, receiver). Finally return new Proxy(target, handler). Define a user object, wrap with const logged = withLog(user), assign logged.age = 28 and log console.log(logged.name).

Show example solution
function withLog(target) {
  const handler = {
    get(target, prop, receiver) {
      console.log('get', prop);
      return Reflect.get(target, prop, receiver);
    },
    set(target, prop, value, receiver) {
      console.log('set', prop, value);
      return Reflect.set(target, prop, value, receiver);
    }
  };
  return new Proxy(target, handler);
}
const user = { name: 'Alex' };
const logged = withLog(user);
logged.age = 28;
console.log(logged.name);

Test yourself

  1. Which two techniques does the logging wrapper combine?

    • Only Symbol.iterator
    • Proxy and Reflect
    • Only the decorator
    • typeof and instanceof
    Show answer

    Proxy and Reflect — Correct! withLog sets up a Proxy and uses Reflect to apply the default behavior after logging.

  2. Match each technique to its use case

    Proxy
    Validate assignment
    Reflect
    Default behavior
    Symbol.iterator
    Traverse with for...of
    Decorator
    Wrap function

All lessons in Expert