Leaderboard
Javascript Jun 10, 2026
Javascript Proxy Get Trap Default Value

JavaScript Proxy — What does this print?

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Proxy Get Trap Default Value and improve your technical interview readiness.

const handler = {
  get(target, key) {
    return key in target ? target[key] : 37
  }
}
const p = new Proxy({}, handler)
p.a = 1
console.log(p.a)
console.log(p.b)
A 1 and undefined
B 1 and 37
C 37 and 37
D 1 and null

Detailed Explanation

Why This Question Matters

If you've spent any time with modern JavaScript frameworks, you've likely interacted with Proxies without even knowing it. Vue 3's reactivity system is built almost entirely on them. But while we use the *results* of Proxies every day, the actual mechanics of how they intercept operations can be surprisingly trippy.

This specific challenge is a classic "gotcha." It tests whether you actually understand how the get trap works and, more importantly, whether you realize that intercepting a read doesn't automatically intercept a write.

Most developers see the get trap and assume the Proxy is now "controlling" the object. In reality, a Proxy is surgical. If you don't define a specific trap for a specific action, JavaScript just does the default behavior.

Understanding the Code

Let's look at the snippet again:

const handler = {
  get(target, key) {
    return key in target ? target[key] : 37
  }
}
const p = new Proxy({}, handler)
p.a = 1
console.log(p.a)
console.log(p.b)

Here is what's happening under the hood.

First, we define a handler object. This is basically a set of rules. We've defined a get trap, which tells JavaScript: *"Whenever someone tries to read a property from this proxy, run this function instead of just returning the value."*

The logic inside the get trap is simple: if the key exists in the target object, return it. If it doesn't, return 37.

Then we create the proxy p wrapping an empty object {}.

Now, here is the part where people trip up: p.a = 1.

This is a set operation, not a get operation. Since our handler only has a get trap and no set trap, the Proxy just lets this assignment pass through to the target object. The target object (which was {}) now becomes { a: 1 }.

Finding the Correct Answer

When we hit the console.log statements, the get trap finally kicks in.

1. console.log(p.a)
The engine calls the get trap. It checks: is 'a' in target?. Yes, it is. The target is { a: 1 }. So it returns target['a'], which is 1.

2. console.log(p.b)
The engine calls the get trap again. It checks: is 'b' in target?. No, it isn't. According to our logic, if the key is missing, we return 37.

The result: 1 and 37.

If you guessed that p.a = 1 would be ignored or that p.a would return 37 because of some weird proxy magic, you're forgetting that the get trap only triggers during *reads*.

Common Mistakes Developers Make

The biggest mistake is assuming the Proxy is a "black box" that handles everything.

Beginners often think that if they define one trap, they've "hooked" the object. But Proxies are explicit. If you want to control how values are written, you must implement the set trap. If you want to control how properties are deleted, you need the deleteProperty trap.

Another common point of confusion is the target. In this example, the target is an empty object. Some developers mistakenly think the handler *is* the object, or that the proxy replaces the target. It doesn't. The proxy is just a middleware layer. The target object is where the data actually lives.

Lastly, watch out for the in operator. In this challenge, key in target is used. If the developer had used target[key] || 37, the result would be different if p.a was set to 0 or false, because those are falsy values. Using in is the correct way to check for property existence.

Real-World Usage

You won't often write a proxy just to return the number 37, but this pattern is everywhere in production.

Default Values and Fallbacks
Imagine you're building a configuration object for a large app. Instead of writing a dozen if (!config.timeout) { timeout = 3000 } checks throughout your code, you can wrap your config in a Proxy. If a requested setting doesn't exist, the get trap can return a sensible default.

API Mocking
Proxies are incredible for testing. You can create a "mock" object that logs every time a property is accessed or returns a fake response without having to manually define every single possible method or property on a mock object.

Observables
As mentioned, Vue 3 uses this to track dependencies. When a component reads a property (get), Vue marks that property as a dependency. When that property is changed (set), Vue knows exactly which components need to re-render.

Key Takeaways

- Traps are specific. A get trap only handles reads. To handle writes, you need a set trap.
- The target is the source of truth. The Proxy is just a wrapper that intercepts calls.
- in is your friend. When checking for property existence in a Proxy, use the in operator to avoid bugs with falsy values.
- Proxies are powerful middleware. They allow you to define custom behavior for fundamental language operations, making them ideal for reactivity and configuration systems.

Why this matters

Understanding Proxy Get Trap Default Value is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.

📝
Reviewed by CodeShot Editorial
Every challenge is code-reviewed by senior developers to ensure accuracy and real-world relevance. Learn more.

Ready for your shot?

Join thousands of developers solving one logic puzzle every morning.

Solve Today's Challenge →