Skip to the solution
MediumDSA8 min read

How would you use Reflect.ownKeys() inside a Proxy to correctly enumerate both string and symbol keys, including non-enumerable ones?

267 views

The problem

Question presented to candidate: "If you needed to write a logging Proxy that reports every single own property key an object has, including symbol keys and non-enumerable string keys, how would you implement the ownKeys trap? Why would Object.keys or a plain for...in loop not be good enough here, and what happens if your trap forgets to include a key the target actually has?"

What a strong answer should cover:

  • Object.keys(), for...in, and JSON.stringify only ever see ENUMERABLE STRING keys β€” they silently skip non-enumerable string keys and skip every symbol key entirely, with no error or warning.
  • Reflect.ownKeys() is the one method that returns everything: every own string key AND every own symbol key, enumerable or not, in the spec-defined order.
  • That order is not insertion order across the board β€” it is integer-like keys first in ascending numeric order, then remaining string keys in insertion order, then symbol keys in insertion order.
  • A Proxy's ownKeys trap should generally just return Reflect.ownKeys(target) (or something equivalent to it) rather than something ad hoc like Object.keys(target), which would silently under-report.
  • The ownKeys trap has real, spec-enforced invariants: its result must include every non-configurable own key of the target, or a real TypeError is thrown β€” this is not merely a convention, it is enforced by the engine.
  • A getOwnPropertyDescriptor trap usually needs to be implemented alongside ownKeys (forwarding to Reflect.getOwnPropertyDescriptor), since Object.keys internally calls both traps to filter down to enumerable keys.

Clarifying questions expected:

  • "Does this proxy need to intercept property reads and writes too, or is enumeration the only behavior being customized?" β€” clarifies whether a minimal handler (just ownKeys + getOwnPropertyDescriptor) is sufficient.
  • "Should the logging happen on every enumeration call, or only once when the proxy is first created?" β€” a real design question about where the instrumentation actually belongs.

Code / implementation expected: Yes β€” a real Proxy with an ownKeys trap plus a runnable test proving the real key ordering and a real invariant-violation TypeError.

  • reflect
  • tricky
  • real-world

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 8 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

JavaScriptA logging Proxy built on Reflect.ownKeys, plus real proof of key ordering and the ownKeys invariant throwing (run directly)

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 104 of 165 in JavaScript

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

When would you reach for Map.groupBy() instead of Object.groupBy(), and what problem does it solve with non-string keys?

Continue