Purpose: inherit only the object keys, not the ones inherited
Two constructor: Person and Teacher. Teacher is inheriting properties using prototypal inheritance.
Height and weight are the two keys inherited from person to teacher.
To my understanding for ... in loops through all the keys in the object as well as keys inherited. Therefore hasOwnProperty is used to filter the properties only available within the Teacher object. However the code outputs all the properties including height and weight which it should not.
/* eslint-disable no-console */
function Person(first, last, age, gender, interests, weight, height) {
this.name = {
first,
last,
};
this.age = age;
this.gender = gender;
this.interests = interests;
this.weight = weight;
this.height = height;
}
Person.prototype.greeting = () => {
console.log(`Hi! I'm ${this.name.first}.`);
};
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
Teacher.prototype.greeting = () => {
let prefix;
if (this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
prefix = 'Mr.';
} else if (this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
prefix = 'Mrs.';
} else {
prefix = 'Mx.';
}
console.log(`Hello. My name is ${prefix} ${this.name.last}, and I teach ${this.subject}.`);
};
Teacher.prototype = Object.create(Person.prototype);
Object.defineProperty(Teacher.prototype, 'constructor', {
value: Teacher,
enumerable: false, // so that it does not appear in 'for in' loop
writable: true,
});
const teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');
for(var key in teacher1){
if(teacher1.hasOwnProperty(key)){
console.log(key);
}
}
// Output: name, age, gender, interests, weight, height, subject
// weight and height should not be here
The name
, age
, etc., properties on teacher1
are own properties. They are not inherited from teacher1
's prototype (Teacher.prototype
) or its prototype (Person.prototype
). Although it's Person
that assigns them, they're still own properties. this
in the call to Person
from Teacher
is the object that will be assigned to teacher1
, so
this.age = age;
...makes age
an own property of teacher1
.
Once the property has been created on the object, there's no way to know what function (if any) created it.
There are a couple of other problems with your code:
You're assigning an arrow function to Teacher.prototype.greeting
. Don't use arrow functions for methods that will be inherited, this
won't be set correctly. A couple of related questions whose answers may be useful:
You're assigning to Teacher.prototype.greeting
, then later replacing Teacher.prototype
entirely (Teacher.prototype = Object.create(Person.prototype);
). So you won't have the greeting
method on it.
If you replace the object on Teacher.prototype
the way you are, it's important to make sure its constructor
property is correct:
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher; // <===
But: Since you're using ES2015+ features anyway (arrow functions, template literals, ...), you can make this all much simpler by using class
syntax.