Hiding Property Existence Using the has
Trap
The in
operator determines whether a property exists on a given object and returns true
if there is either an own property or a prototype property matching the name or symbol. For example:
let target = {
value: 42;
}
console.log("value" in target); // true
console.log("toString" in target); // true
Both value
and toString
exist on object
, so in both cases the in
operator returns true
. The value
property is an own property while toString
is a prototype property (inherited from Object
). Proxies allow you to intercept this operation and return a different value for in
with the has
trap.
The has
trap is called whenever the in
operator is used. When called, two arguments are passed to the has
trap:
trapTarget
- the object the property is read from (the proxy’s target)key
- the property key (string or symbol) to check
The Reflect.has()
method accepts these same arguments and returns the default response for the in
operator. Using the has
trap and Reflect.has()
allows you to alter the behavior of in
for some properties while falling back to default behavior for others. For instance, suppose you just want to hide the value
property. You can do so like this:
let target = {
name: "target",
value: 42
};
let proxy = new Proxy(target, {
has(trapTarget, key) {
if (key === "value") {
return false;
} else {
return Reflect.has(trapTarget, key);
}
}
});
console.log("value" in proxy); // false
console.log("name" in proxy); // true
console.log("toString" in proxy); // true
The has
trap for proxy
checks to see if key
is "value"
returns false
if so. Otherwise, the default behavior is used via a call to the Reflect.has()
method. As a result, the in
operator returns false
for the value
property even though value
actually exists on the target. The other properties, name
and toString
, correctly return true
when used with the in
operator.