If I understand correctly, object.hasOwnProperty()
should return false on inherited properties of the parent class. However, the following code returns true on both own and inherited properties.
Is my understanding/code incorrect or is hasOwnPropery()
incorrect?
If it's me, how do I discriminate between own and inherited properties?
Edit: I've added my use case to the sample code.
I would expect the child's fromDb()
would only take care of its own properties, instead, it overrides the properties set by the parent's fromDb()
.
class Parent {
parentProp = '';
fromDb(row: {}) {
for (const key of Object.keys(row)) {
if (this.hasOwnProperty(key)) {
if (key === 'parentProp') {
// Do some required data cleansing
this[key] = row[key].toUpperCase()
} else {
this[key] = row[key];
}
}
};
return this;
}
}
class Child extends Parent {
childProp = '';
fromDb(row: {}) {
super.fromDb(row);
for (const key of Object.keys(row)) {
if (this.hasOwnProperty(key)) {
this[key] = row[key];
}
};
return this;
}
}
let row = {
parentProp: 'parent',
childProp: 'child',
}
let childObj = new Child().fromDb(row);
console.log(childObj);
Console:
Child:
childProp: "child"
parentProp: "parent"
In the generated extends
code, properties are copied to the subclass like this:
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
Which means that your subclass (d
) is given it's own property.
This is actually no different to using plain JavaScript inheritance:
function Parent() {
this.parentProp = `I'm defined by Parent`;
}
function Child() {
Parent.call(this);
this.childProp = `I'm defined by Child`;
}
let childObj = new Child();
for (const key of Object.keys(childObj)) {
console.log(key, childObj.hasOwnProperty(key));
}
If you give us some direction on what you need to achieve, I'm sure we'll find a suitable mechanism for you that will overcome this obstacle.
For your specific use case, you can set the precedent for who "wins" by where you call the superclass.
To get the output
childProp: "child"
parentProp: "PARENT"
Let the parent run "second", rather than "first":
class Child extends Parent {
childProp = '';
fromDb(row: {}) {
for (const key of Object.keys(row)) {
if (this.hasOwnProperty(key)) {
this[key] = row[key];
}
};
super.fromDb(row); // <-- last update wins
return this;
}
}
This will dynamically exclude parent keys from the child and child keys from the parent... add console.log
statements to see the internals...
class Parent {
parentProp = '';
fromDb(row: {}) {
const ownKeys = Object.keys(new Parent());
for (const key of Object.keys(row)) {
if (ownKeys.indexOf(key) > -1) {
if (key === 'parentProp') {
// Do some required data cleansing
this[key] = row[key].toUpperCase()
} else {
this[key] = row[key];
}
}
};
return this;
}
}
class Child extends Parent {
childProp = '';
fromDb(row: {}) {
super.fromDb(row);
const ownKeys = this.getKeys();
for (const key of Object.keys(row)) {
if (ownKeys.indexOf(key) > -1) {
this[key] = row[key];
}
};
return this;
}
getKeys() {
const childKeys = Object.keys(this);
const parentKeys = Object.keys(new Parent());
return childKeys.filter( function( el ) {
return parentKeys.indexOf( el ) < 0;
});
}
}
let row = {
parentProp: 'parent',
childProp: 'child',
}
let childObj = new Child().fromDb(row);
console.log(childObj);
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