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']
getOwnPropertyNames(a) returns all own properties of the object a . Object. keys(a) returns all enumerable own properties. It means that if you define your object properties without making some of them enumerable: false these two methods will give you the same result.
target : the original object which you want to proxy. handler : an object that defines which operations will be intercepted and how to redefine intercepted operations.
A Proxy is a placeholder object that “traps” invocations and operations made to its target object which it can then passthrough, no-op, or handle more elegantly. It creates an undetectable barrier around the target object that redirects all operations to the handler object.
Object. getOwnPropertyNames() returns an array whose elements are strings corresponding to the enumerable and non-enumerable properties found directly in a given object obj . The ordering of the enumerable properties in the array is consistent with the ordering exposed by a for...in loop (or by Object.
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']
The difference between Object.keys
and Object.getOwnPropertyNames
is that the latter returns own properties regardless of whether or not they are enumerable.
The properties added to the object by Proxy
are non-enumerable, and won't show up in Object.keys
, but will in Object.getOwnPropertyNames
Generally, properties added by assignment or a property initializer are enumerable by default, and properties added with methods such as Object.assign
, new Proxy
etc. are non-enumerable by default.
There's more on property ownership and enumerability on MDN, where one can also find this table that outlines the difference in the two methods
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With