admin管理员组

文章数量:1279181

I’m trying to use a JavaScript Proxy to hide a property from detection while keeping it in the target object. The has trap successfully makes 'secret' in proxy return false, but the property is still accessible directly.

Code Example:

const target = { secret: 123, public: 456 };
const proxy = new Proxy(target, {
  has(t, prop) {
    if (prop === 'secret') return false; // Hide from `in` checks
    return prop in t;
  }
});

console.log('secret' in proxy); 
console.log(proxy.secret);      

Questions:

  1. Why does the in operator not block direct access to the property?
  2. How can I fully hide a property in a Proxy so it’s undetectable and inaccessible?
  3. Are there specific traps (e.g., get, ownKeys) that must be implemented together for consistency?

Observed Behavior:

  • 'secret' in proxy correctly returns false.
  • proxy.secret still returns the value 123.

Expected Behavior:
If the in operator returns false for 'secret', accessing proxy.secret should throw an error or return undefined.

Attempts to Fix:

  1. Tried using only the has trap.
  2. Researched other traps like get and ownKeys but unsure how to coordinate them.

I’m trying to use a JavaScript Proxy to hide a property from detection while keeping it in the target object. The has trap successfully makes 'secret' in proxy return false, but the property is still accessible directly.

Code Example:

const target = { secret: 123, public: 456 };
const proxy = new Proxy(target, {
  has(t, prop) {
    if (prop === 'secret') return false; // Hide from `in` checks
    return prop in t;
  }
});

console.log('secret' in proxy); 
console.log(proxy.secret);      

Questions:

  1. Why does the in operator not block direct access to the property?
  2. How can I fully hide a property in a Proxy so it’s undetectable and inaccessible?
  3. Are there specific traps (e.g., get, ownKeys) that must be implemented together for consistency?

Observed Behavior:

  • 'secret' in proxy correctly returns false.
  • proxy.secret still returns the value 123.

Expected Behavior:
If the in operator returns false for 'secret', accessing proxy.secret should throw an error or return undefined.

Attempts to Fix:

  1. Tried using only the has trap.
  2. Researched other traps like get and ownKeys but unsure how to coordinate them.
Share Improve this question asked Feb 23 at 23:44 Yash SanghviYash Sanghvi 1 1
  • 2 "Why does the in operator not block direct access to the property?" - because property access does not use the in operator. Yes, you need to implement get, and have all the traps coordinate. – Bergi Commented Feb 24 at 0:02
Add a comment  | 

1 Answer 1

Reset to default 4

Yes, you need to coordinate the all related traps, you could make a generic function to hide object keys.

Note that in looks in the prototype chain so for handling class instances with inheritance there could be more complex logic required.

const hideKeys = (target, keys) => {
  keys = new Set(keys);
  return new Proxy(target, {
    get(t, prop){
      if(keys.has(prop)) return;
      return Reflect.get(...arguments)
    },
    has(t, prop) {
      if (keys.has(prop)) return false; // Hide from `in` checks
      return Reflect.has(...arguments);
    },
    ownKeys(){
      return Reflect.ownKeys(...arguments).filter(key => !keys.has(key));
    },
    getOwnPropertyDescriptor(t, prop){
      if(keys.has(prop)) return;
      return Reflect.getOwnPropertyDescriptor(...arguments);
    }
  });
}

const target = { secret: 123, public: 456 };

const proxy = hideKeys(target, ['secret']);

console.log('secret' in proxy);
console.log(Object.hasOwn(proxy, 'secret'));
for(const k in proxy){
  console.log(k);
}
console.log(proxy.propertyIsEnumerable('secret'));
console.log(proxy.secret);
console.log(JSON.stringify(proxy));

本文标签: