How can support Object.entries being called on an instance of my class - javascript / nodejs?
Solution 1:
The issue is that your instances have no public "own" (not inherited) properties, which is what Object.entries
includes in its array.
I am trying to get my class to behave like a "normal" object, in that when it is called in object.entries it returns an array of key value pairs.
That's the default behavior, whether you create the object via a class constructor or some other way.
After quite a bit of searching around I have been able to make my class iterable.
Object.entries
has nothing to do with whether an object is iterable.
I don't think you can make Object.entries
return [[name, "value"]]
without making name
an "own" data property. But you can make it a read-only own data property via Object.defineProperty
:
class Person {
#name;
constructor(name) {
this.#name = name;
Object.defineProperty(this, "name", {
value: name,
writable: false,
enumerable: true,
configurable: true
});
}
}
const bill = new Person("Bill");
console.log(`bill.name:`, bill.name);
console.log(`Object.entries(bill):`, Object.entries(bill));
I've kept #name
there, but there's probably no reason for it, so:
class Person {
constructor(name) {
Object.defineProperty(this, "name", {
value: name,
writable: false,
enumerable: true,
configurable: true
});
}
}
const bill = new Person("Bill");
console.log(`bill.name:`, bill.name);
console.log(`Object.entries(bill):`, Object.entries(bill));
If you want to be able to set name
internally, just give yourself a private method that repeates the defineProperty
:
class Person {
constructor(name) {
this.#setName(name);
}
#setName(name) {
Object.defineProperty(this, "name", {
value: name,
writable: false,
enumerable: true,
configurable: true
});
}
}
const bill = new Person("Bill");
console.log(`bill.name:`, bill.name);
console.log(`Object.entries(bill):`, Object.entries(bill));
Unfortunately, because the property is configurable, your code isn't the only code that can use defineProperty
to change it. (This is rather like the name
property on functions, which is read-only by default but can be changed via defineProperty
.) So it's not exactly the same as having #name
and get name
, it's just close while providing support for Object.entries
.