Okay, so according to my knowledge, we would write a class constructor like so
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
//anything outside of constructor belong to this.prototype
getName() {
console.log(this.name);
}
getAge() {
console.log(this.age);
}
}
So instead, if I write something like this:
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
getName() {
console.log(this.name);
}
}
User.prototype.getAge = function () {
console.log(this.age);
};
It should technically be exactly the same, right? Or I am wrong? Because when I tried this which each one, I get 2 different result:
let user = new User('john', 23);
let properties = [];
for (let prop in user) {
properties.push(prop);
}
console.log(properties); //The first code result : ["name", "age"]
//The second code result : ["name", "age", "getAge"]
So what is the difference between the two?
The difference between the two is that using User.prototype.getAge = ...
will add the property with the property descriptor enumerable: true
. This means it shows up in for...in
loops.
The
for...in
statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
getName() {
console.log(this.name);
}
}
User.prototype.getAge = function () {
console.log(this.age);
};
let user = new User('john', 23);
let properties = [];
for (let prop in user) {
properties.push(prop);
}
console.log(properties);
console.log(Object.getOwnPropertyDescriptor(User.prototype, "getName"));
console.log(Object.getOwnPropertyDescriptor(User.prototype, "getAge"));
If you want to define the prototype the exact same way you'll have to use the same property descriptor. This can be achieved with Object.defineProperty()
:
Object.defineProperty(User.prototype, "getAge", {
value: function () {
console.log(this.age);
},
writable: true,
enumerable: false,
configurable: true,
});