DEV Community

Cover image for The Secret Life of JavaScript: The Proxy
Aaron Rose
Aaron Rose

Posted on

The Secret Life of JavaScript: The Proxy

How to use Metaprogramming to intercept and validate your data.


Timothy sat at his desk, looking a bit overwhelmed. He had a simple user object, but his code was cluttered with if statements.

let user = {
    name: "Timothy",
    age: 25
};

// Timothy's validation code
if (user.age < 0) {
    throw new Error("Age cannot be negative!");
}
user.age = -5; // He was trying to prevent this

Enter fullscreen mode Exit fullscreen mode

"I want to protect my data," Timothy said softly, "but I don't want to clutter my object with validation logic in every single function. Is there a cleaner way?"

Margaret smiled warmly. She pulled a chair up next to him, not as a critic, but as a guide.

"That is a very mature instinct, Timothy," she said. "You are looking for Metaprogramming. Specifically, a tool called the Proxy."

The Middleman

Margaret drew a circle on the chalkboard and labeled it Target.

"Normally, when you interact with an object, you are speaking directly to it," she explained. "The Proxy allows you to place a 'Middleman' in front of that object."

She wrote the syntax:

const proxy = new Proxy(target, handler);

Enter fullscreen mode Exit fullscreen mode

"The Target is your original object," she said. "The Handler is an object that defines the rules. It contains 'traps' that intercept your interactions."

Trap 1: Intercepting Reads (get)

"Let's try a harmless prank to see how it works," Margaret said with a twinkle in her eye. "Let's teach the engine to lie."

She wrote a handler that intercepted the get operation.

const user = { name: "Timothy" };

const handler = {
    get(target, prop) {
        if (prop === "name") {
            return "The Great " + target[prop];
        }
        return target[prop];
    }
};

const proxyUser = new Proxy(user, handler);

console.log(proxyUser.name); // "The Great Timothy"

Enter fullscreen mode Exit fullscreen mode

Timothy's eyes widened. "I didn't change the object. I just changed how I read it."

"Exactly," Margaret nodded. "In the real world, developers use this to log data access or create 'private' properties. But the concept is the same: The Proxy decides what to return, not the object."

Trap 2: Validation (set)

"Now, for your problem," Margaret said gently. "You want to stop invalid data from ever touching your object. We can use the set trap."

She wiped the board and wrote a new handler.

const validator = {
    set(target, prop, value) {
        if (prop === "age" && value < 0) {
            console.error("Age must be positive, Timothy.");
            return false; // Reject the change
        }

        target[prop] = value;
        return true; // Accept the change
    }
};

const secureUser = new Proxy(user, validator);

secureUser.age = 25; // Works fine
secureUser.age = -10; // Error: Age must be positive, Timothy.

Enter fullscreen mode Exit fullscreen mode

Timothy smiled. "It's like a bodyguard. The bad data never even reaches the user object."

"Precisely," Margaret said. "You have separated your Logic (the validator) from your Data (the user). That is the hallmark of clean architecture."

The Toolkit: Reflect and Other Traps

"Is that all it can do?" Timothy asked.

"Hardly," Margaret laughed. "You can intercept almost anything."

She listed a few more capabilities:

  • has trap: Intercepts the in operator (hiding keys).
  • deleteProperty trap: Prevents properties from being deleted.
  • apply trap: Intercepts function calls.

"And to make this easier," she added, "we use the Reflect API. It allows us to perform the default behavior without manually modifying the target."

set(target, prop, value) {
    if (value < 0) return false;
    return Reflect.set(target, prop, value); // "Okay, proceed as normal."
}

Enter fullscreen mode Exit fullscreen mode

The Conclusion

Timothy looked at his code. The clutter was gone. The logic was safe.

"Thank you, Margaret," he said. "I feel like I have superpowers. I can change how the language behaves."

Margaret patted him on the shoulder. "You do, Timothy. But remember the Golden Rule of Metaprogramming."

"What is that?"

"Magic comes with a cost. Proxies add a small performance overhead to every operation. Use them for critical validation, not for every single object in your system. Use your powers for clarity, not confusion."


Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.

Top comments (0)