const Person = function (firstName, birthYear) {
this.firstName = firstName;
this.birthYear = birthYear;
};
Person.prototype.calcAge = function () {
console.log(2037 - this.birthYear);
};
const Student = function (firstName, birthYear, course) {
// Person(firstName, birthYear); // error, this doesn't work as expected as without the `new` operator, this is just a function call and `this` inside a function call is set to undefined
Person.call(this, firstName, birthYear); // use this to manually set `this` as well
this.course = course;
};
// Linking prototypes
//Student.prototype = Person.prototype // this is wrong as this this is basically the equivalence of saying these two objects are the same while we are trying to link the Student prototype to Person prototype
Student.prototype = Object.create(Person.prototype); // do this
Student.prototype.introduce = function () {
console.log(`My name is ${this.firstName} and I study ${this.course}`);
};
const mike = new Student('Mike', 2020, 'Computer Science');
mike.introduce();
mike.calcAge();
console.log(mike.__proto__);
console.log(mike.__proto__.__proto__);
console.log(mike instanceof Student); // true
console.log(mike instanceof Person); // true
console.log(mike instanceof Object); // true
console.dir(Student.prototype.constructor); // this should point to Student but it instead points to Person
Student.prototype.constructor = Student; // fix it with this
console.dir(Student.prototype.constructor); // it correctly point to Student now
Basically the above but in a more convenient syntax.
class PersonCl {
constructor(fullName, birthYear) {
this.fullName = fullName;
this.birthYear = birthYear;
}
// Instance methods
calcAge() {
console.log(2037 - this.birthYear);
}
greet() {
console.log(`Hey ${this.fullName}`);
}
get age() {
return 2037 - this.birthYear;
}
set fullName(name) {
if (name.includes(' ')) this._fullName = name;
else alert(`${name} is not a full name!`);
}
get fullName() {
return this._fullName;
}
// Static method
static hey() {
console.log('Hey there 👋');
}
}
class StudentCl extends PersonCl {
constructor(fullName, birthYear, course) {
// Always needs to happen first!
super(fullName, birthYear);
this.course = course;
}
introduce() {
console.log(`My name is ${this.fullName} and I study ${this.course}`);
}
calcAge() {
console.log(
`I'm ${
2037 - this.birthYear
} years old, but as a student I feel more like ${
2037 - this.birthYear + 10
}`
);
}
}
const martha = new StudentCl('Martha Jones', 2012, 'Computer Science');
martha.introduce();
martha.calcAge();