JavaScript
Completed
-
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)
243: The Reflect Object
If you've spent any time with Proxy objects, you know they're incredibly powerful for intercepting operations. But there's a common point of confusion: why do we need the Reflect object? Why can't we just manipulate the target object directly inside our traps?
I used to think Reflect was just "syntactic sugar"—a fancy way of doing things we already knew how to do. I was wrong. Reflect provides a set of methods that mirror the internal operations of JavaScript. When you're inside a Proxy trap, using Reflect ensures that the default behavior of the language is preserved, especially when dealing with inheritance or complex getters and setters.
Building a guarded configuration object
Let's build a configuration manager. I want an object where I can track every time a setting is changed, and I want to prevent certain "frozen" settings from being deleted. Instead of writing a bunch of wrapper functions, we'll use a Proxy.
const appConfig = { theme: 'dark', apiEndpoint: 'https://api.example.com', version: '1.0.0' }; const handler = { get(target, prop, receiver) { console.log(`Reading ${prop}...`); return Reflect.get(target, prop, receiver); }, deleteProperty(target, prop) { if (prop === 'version') { console.warn('The version property is protected!'); return false; } return Reflect.deleteProperty(target, prop); } }; const config = new Proxy(appConfig, handler);Notice that I used
Reflect.getandReflect.deleteProperty. In thedeletePropertytrap,Reflect.deletePropertyis particularly clean because it returns a boolean indicating whether the operation succeeded, which is exactly what the Proxy trap expects.The mistake: Ignoring the receiver
Here is where I usually tripped up when I first started using Proxies. Let's add a
settrap. At first, I might have written it like this:// My initial mistake set(target, prop, value) { console.log(`Setting ${prop} to ${value}`); target[prop] = value; // Direct assignment return true; }This looks fine, right? For a simple object, it is. But if our
appConfiginherited from another object that had a setter,target[prop] = valuewould bypass the Proxy'sreceiver. This means thethiscontext inside that setter would be the originaltargetobject, not our Proxy. That's a recipe for subtle, nightmare-inducing bugs in larger applications.To fix this, I'll use
Reflect.set, which takes that thirdreceiverargument:set(target, prop, value, receiver) { console.log(`Updating ${prop} to ${value}`); // Using Reflect ensures the 'this' context remains the Proxy (receiver) return Reflect.set(target, prop, value, receiver); }Why this matters in the real world
By using
Reflect.set(target, prop, value, receiver), we aren't just assigning a value; we're telling JavaScript, "Perform the default 'set' operation, but make sure you do it as if the Proxy was the object being acted upon."If you're just building a quick prototype, direct assignment is tempting. But as an engineer, you want your utilities to be robust.
Reflectturns the "magic" of Proxies into a predictable, standard API. It separates the interception (the Proxy) from the execution (Reflect).
📋 Practical Task
Implementing a Read-Only API Key Guard
You are building a security wrapper for a credentials object. Your goal is to create a Proxy that allows any property to be read or modified, except for the apiKey property, which should be read-only.
Requirements:
- Create an object called
credentialswith at least two properties:usernameandapiKey. - Implement a Proxy handler with a
settrap. - Inside the
settrap, if the property being changed is'apiKey', log "Error: apiKey is read-only" and returnfalse. - For all other properties, use
Reflect.setto update the value, ensuring you pass thereceiverargument. - Test your implementation by attempting to change both the
usernameand theapiKey.
There are no comments for now.