Following this question: Object.prototype
returns empty object in Node which asked
Why doesn't
console.log(Object.prototype)
log the expected object and instead returns{}
.
Here was the answer:
It is because the
console.log
[...] usesObject.keys()
on objects, and it returns enumerable properties only. AndObject.prototype
contains non-enumerable properties, that is why it returns an empty node.
I was wondering how I could output all properties of a given object (for instance Object.prototype
). As shown by another answer, using getOwnPropertyNames
works fine:
const ObjectPrototype = Object.getOwnPropertyNames(Object.prototype).reduce((object, name) => {
object[name] = Object.prototype[name];
return object;
}, {});
console.log(
ObjectPrototype
);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I thought I could extract the hidden properties of a given object this way. But actually, it doesn't fully work.
Here's an easier example: the object I'm inspecting is the object {mykey: 'value'}
. Chrome gives me its property (console.log
does too) but also its prototype, __proto__
greyed out:
let object = { mykey: 'value' };
object = Object.getOwnPropertyNames(object).reduce((acc, name) => {
acc[name] = object[name];
return acc;
}, {});
console.log(
object
);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The above only returns one property. I was expecting to also have __proto__
. Is there a way to show all of one's properties including hidden ones? Or do I manually have to access it: i.e. reduce Object.getOwnPropertyNames(object.__proto__)
?
PS: or in other words, how does Chrome handle hidden properties?
You can write a function, let's call it getAllPropertyNames()
, that iterates through the prototype chain of the object and accumulates the properties of each level:
function getAllPropertyNames (o) {
let propertyNames = []
for (let proto = o; proto !== null; proto = Object.getPrototypeOf(proto)) {
propertyNames = propertyNames.concat(Object.getOwnPropertyNames(proto))
}
return propertyNames
}
console.log(getAllPropertyNames({ mykey: 'value' }))
These properties aren't hidden, they're just inherited, which is why getOwnPropertyNames()
does not include them. They're not specific to the object, but rather everything that inherits from Object.prototype
.
I'm going to attempt something a little unconventional, but should produce the desired output:
// probably could be named better
// feel free to suggest one in comments
function asEnumerable (o) {
const acc = Object.create(null)
for (let oProto = o, aProto = acc; oProto !== null; oProto = Object.getPrototypeOf(oProto), aProto = aProto.__proto__) {
for (const key of Object.getOwnPropertyNames(oProto)) {
aProto[key] = oProto[key]
}
if (Object.getPrototypeOf(oProto) !== null) {
aProto.__proto__ = Object.create(null)
}
}
return acc
}
console.log(asEnumerable({ mykey: 'value' }))
.as-console-wrapper{min-height:100%!important}
This implementation does abide to the specification, since it does not treat __proto__
as if it modifies inheritance of the object, but simply as a normal property on acc
and aProto
.