-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
245: Practice Exercise: Building a Validation Proxy
Think of a Proxy as a strict office manager sitting at a desk between you and a filing cabinet. If you want to put a document into a folder, you don't just walk up and slide it in yourself. Instead, you hand the document to the manager. They look it over, make sure it's signed in the right place and filled out correctly, and only then do they open the drawer and file it for you. If the document is missing a signature, they hand it back to you and tell you exactly why it's being rejected.
In JavaScript, that filing cabinet is your target object (the raw data), and the manager is the handler. The act of trying to change a value is the set trap. By placing a Proxy in front of your data, you can stop invalid state from ever entering your application, rather than trying to find and fix the bug after the data has already been corrupted.
The Secretary in the Middle
When we build a validation proxy, we're primarily interested in the set trap. This function runs every time someone tries to assign a value to a property. I've found that in large-scale apps, this is a lifesaver because it centralizes your business logic. Instead of having if (age < 0) checks scattered across five different UI components, you put that logic in one Proxy handler.
const userConstraints = {
age: (val) => typeof val === 'number' && val >= 0,
username: (val) => typeof val === 'string' && val.length >= 3
};
const handler = {
set(target, prop, value) {
if (prop in userConstraints) {
const validator = userConstraints[prop];
if (!validator(value)) {
throw new TypeError(`Invalid value for ${prop}: ${value}. Check your constraints.`);
}
}
// If it passes validation, or there is no constraint, we actually update the object
target[prop] = value;
return true; // Success!
}
};
const rawUser = { username: 'dev_jane', age: 28 };
const userProxy = new Proxy(rawUser, handler);
userProxy.age = 30; // Works fine
userProxy.age = -5; // Throws TypeError: Invalid value for age: -5.
Turning Rules into Traps
Notice that return true at the end of the set trap. I see a lot of developers forget this. In strict mode, if the set trap returns false (or nothing at all), JavaScript will throw a TypeError because the assignment failed. It's the Proxy's way of saying, "I tried to do this, but it didn't happen."
I prefer using a separate constraints object (like userConstraints above) rather than hardcoding if/else blocks inside the handler. It makes your proxy reusable. If your requirements change—say, the username now needs to be 5 characters instead of 3—you only change one line in your configuration object, not the logic of the Proxy itself.
Why Not Just Use a Setter?
You might be wondering why we aren't just using setters in a class. Setters are great, but they require you to define every single property upfront. Proxies are dynamic. If you add a new property to your object that isn't in your constraints list, the Proxy just lets it through. It provides a "safety net" for the things you care about without getting in the way of the things you don't.
📋 Practical Task
Exercise: Implementing a Strict Product Catalog Validator
You are building a product management system. You need to ensure that any product added to the catalog has a valid price (a positive number) and a valid SKU (a string that starts with 'PROD-').
Your Task:
- Create a target object called
productwith initial values forname,price, andsku. - Create a
handlerobject with asettrap. - Inside the
settrap, implement the following validation rules:- If the property is
price, it must be a number and greater than 0. - If the property is
sku, it must be a string and begin with the prefix"PROD-". - If the validation fails, throw a
RangeErrorwith a descriptive message.
- If the property is
- Initialize a
productProxyusing the target and handler. - Test your proxy by attempting to set a negative price and an invalid SKU to ensure the errors are thrown.
There are no comments for now.