강의 출처 : The Complete JavaScript Course 2022 Jonas (Udemy)
예시) 각각 Constructor function으로 만들어진 Parent Class인 Person과 Child Class인 Student가 있다고 가정하자. Student는 Person의 methods와 propeties를 상속받을 수 있고 좀더 구체적이다. 이러한 Prototype Chain을 만들기 위해서는 Object.creat()을 사용할 수 있다.
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.call(this, firstName, birthYear);
//this는 새로 만들어진 object를 가리킨다.
//단순히 Person(firstName, birthYear)로 하면 안됌.
//단순한 function expression이기 때문에 여기서의 this가 undefined를 가리킴.
this.course = course;
};
// Linking prototypes
Student.prototype = Object.create(Person.prototype);
// 유의) Student.prototype = Person.prototype 은 전혀 작동하지 않음.
Student.prototype.introduce = function () {
console.log(`My name is ${this.firstName} and I study ${this.course}`);
};
const mike = new Student('Mike', 2020, 'Computer Science');
console.log(mike);
mike.introduce(); //My name is Mike and I study Computer Science
mike.calcAge(); //17 => prototype chain 으로 인해 Person 내에 있는 method를 이용할 수 있는 것!
console.log(mike.__proto__); //Person {introduce: ƒ}
console.log(mike.__proto__.__proto__); //{calcAge: ƒ, constructor: ƒ}
console.log(mike instanceof Student); //true
console.log(mike instanceof Person); //true
console.log(mike instanceof Object); //true
Student.prototype.constructor = Student;
console.dir(Student.prototype.constructor);
요약그림
만약 Student.prototype = Person.prototype 으로 설정을 한다면
mike라는 object의 prototype은 Person.prototype이 되버림. 꼭 Object.create로 설정해 줄 것!
extends 와 super함수를 이용한다.
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 a property that already exists
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 ✋🏻');
console.log(this);
}
}
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(); //My name is Martha Jones and I study Computer Science
martha.calcAge(); //I'm 25years old, but as a student I feel more like 3
//같은 이름의 함수 child class의 method가 parent class 의 method를 override 한다.
참고)
새로운 properties가 필요 없는 경우 그냥 StudentCl extends PersonCl{} 만 해주면 된다!
constructor 내에서 super 함수는 항상 먼저 실행시켜줄 것!
const PersonProto = {
calcAge() {
console.log(2037 - this.birthYear);
},
init(firstName, birthYear) {
this.firstName = firstName;
this.birthYear = birthYear;
},
};
const steven = Object.create(PersonProto);
const StudentProto = Object.create(PersonProto);
StudentProto.init = function (firstName, birthYear, course) {
PersonProto.init.call(this, firstName, birthYear);
this.course = course;
};
StudentProto.introduce = function () {
console.log(`My name is ${this.firstName} and I study ${this.course}`);
};
const jay = Object.create(StudentProto);
jay.init('Jay', 2010, 'Computer Science');
jay.introduce(); //My name is Jay and I study Computer Science
jay.calcAge(); //27