I have the following proxy:
const p = new Proxy({}, {
ownKeys(target) {
return ['a', 'b'];
},
});
MDN says that:
This trap can intercept these operations:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
Therefore, I expected Object.getOwnPropertyNames()
and Object.keys()
to produce the same output. However, Object.getOwnPropertyNames(p)
returns ['a', 'b']
(as expected), but Object.keys(p)
returns an empty array. Why is that?
Also, if I add a property to this object which is not returned by the ownKeys
handler (for example c
), it gets ignored by both functions (they don't change their output). However, when I add a property which is returned by the ownKeys
handler (for example a
), Object.keys(p)
now returns ['a']
.
Code snippet:
const p = new Proxy({}, {
ownKeys(target) {
return ['a', 'b'];
},
});
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // []
p.c = true;
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // []
p.a = true;
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // ['a']
The difference between Object.keys()
and Object.getOwnPropertyNames()
is that Object.keys()
will invoke [[GetOwnProperty]]
on the object, and only add the property to the result list if the returned property descriptor is enumerable. Since the object doesn't have a such a property, [[GetOwnProperty]]
will return undefined
and the property (name) is ignored.
You can overwrite/implement [[GetOwnProperty]]
in the proxy by implementing getOwnPropertyDescriptor
:
const p = new Proxy({}, {
ownKeys(target) {
return ['a', 'b'];
},
getOwnPropertyDescriptor(k) {
return {
enumerable: true,
configurable: true,
};
}
});
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // ['a', 'b']