🌈 인프런의
코어 자바스크립트(정재남)
수강 후, 이해한 내용을 정리한 글입니다.
📍 아래는 학습을 위해 ES6의 extends를 사용하지 않고 구현한 class inheritance입니다. extends 사용 코드는 맨 아래에 있습니다.
예시로 사용할 2개의 class가 있다. 두 class에는 getName(), getAge()라는 공통된 메서드가 있다.
// Person class
function Person(name, age) {
this.name = name || '이름없음';
this.age = age || '나이모름';
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.getAge = function() {
return this.age;
}
// Employee class
function Employee(name, age, position) {
this.name = name || '이름없음';
this.age = age || '나이모름';
this.position = position || '직책모름';
}
Employee.prototype.getName = function() {
return this.name;
}
Employee.prototype.getAge = function() {
return this.age;
}
Employee.prototype.getPosition = function() {
return this.position;
}
두 class를 연결해 주는 비어있는 class인 Bridge가 필요하다.
Bridge class를 Person class와 겹친다. Person의 instance와 Employee.prototype을 직접 연결하지 않는 이유는 name: '이름없음'
, age: '나이없음'
과 같은 프로퍼티는 제외하고 getName()
, getAge()
와 같은 메서드만 상속하고 싶기 때문이다.
아래와 같다.
// 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
// Person class
function Person(name, age) {
this.name = name || '이름없음';
this.age = age || '나이모름';
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.getAge = function() {
return this.age;
}
// Employee class
function Employee(name, age, position) {
this.name = name || '이름없음';
this.age = age || '나이모름';
this.position = position || '직책모름';
}
// 2️⃣ Bridge class를 생성한다.
function Bridge() {}
// 3️⃣ Bridge.prototype과 상위 class의 prototype을 연결한다.
Bridge.prototype = Person.prototype;
// 4️⃣ 하위 class의 prototype과 Bridge의 instance를 연결한다.
Employee.prototype = new Bridge();
// 5️⃣ 하위 class의 prototype.constructor에 하위 class constructor를 할당한다.
Employee.prototype.constructor = Employee;
// 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.
Employee.prototype.getPosition = function() {
return this.position;
}
var roy = new Employee();
instance roy 생성 후 콘솔을 확인하면 아래와 같이 [[Prototype]]에 Person이 들어가 상속된 것을 볼 수 있다.
Bridge class는 자주 등장하는 패턴이고, 매개체 역할만 할 뿐 실제 코드에 영향을 주지 않는다. 때문에 2️⃣ ~ 5️⃣을 함수화하여 1번만 작성하고 필요할 때마다 불러서 사용할 수 있다.
// 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
// Person class
function Person(name, age) {
this.name = name || '이름없음'; // ⭐️
this.age = age || '나이모름'; // ⭐️
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.getAge = function() {
return this.age;
}
// Employee class
function Employee(name, age, position) {
this.name = name || '이름없음'; // ⭐️
this.age = age || '나이모름'; // ⭐️
this.position = position || '직책모름';
}
// 2️⃣ ~ 5️⃣
var extendClass = (function() {
function Bridge(){}
return function(Parent, Child) {
Bridge.prototype = Parent.prototype;
Child.prototype = new Bridge();
Child.prototype.constructor = Child;
}
})();
// 함수 사용
extendClass(Person, Employee);
// 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.
Employee.prototype.getPosition = function() {
return this.position;
}
var roy = new Employee();
위의 코드에서 ⭐️ 부분이 중복된다. this를 통해 name과 age를 Employee class에 상속하여 코드 중복을 피할 수 있다. ✅ 부분이 변경, 추가되었다.
// 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
// Person class
function Person(name, age) {
this.name = name || '이름없음';
this.age = age || '나이모름';
}
Person.prototype.getName = function() {
return this.name;
}
Person.prototype.getAge = function() {
return this.age;
}
// Employee class
function Employee(name, age, position) {
// 📍 메서드 호출 시 this 호출 => this === 메서드를 호출한 주체 === this === roy
this.superClass(name, age); // ✅ Prototype Chain을 타고 Enployee.prototype에 있는 superClass 호출
this.position = position || '직책모름';
}
// 2️⃣ ~ 5️⃣
var extendClass = (function() {
function Bridge(){}
return function(Parent, Child) {
Bridge.prototype = Parent.prototype;
Child.prototype = new Bridge();
Child.prototype.constructor = Child;
Child.prototype.superClass = Parent; // ✅
}
})();
// 함수 사용
extendClass(Person, Employee);
// 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.
Employee.prototype.getPosition = function() {
return this.position;
}
var roy = new Employee(); // 📍 생성자 함수 호출 시 this 호출 => this === instance === roy
아래처럼 작성하면 위와 동일하게 작동하는 코드를 작성할 수 있다.
class Person() {
constructor(name, age) {
this.name = name || '이름없음';
this.age = age || '나이모름';
}
getName() {
return this.name;
}
getAge() {
return this.age;
}
}
class Employee extends Person {
constructor (name, age, position) {
super(name, age);
this.position = position || '직책모름';
}
getPosition() {
return this.position;
}
}