#8 - 상속과 prototype

만식이형·2023년 5월 31일
0

Javascript

목록 보기
8/10
post-thumbnail

1. 상속

상속은 객체 지향 프로그래밍에서 객체 간의 코드 및 속성을 공유하기 위한 메커니즘이며, 보통은 상위와 하위 객체의 관계를 부모-자식 관계에 빗대어 표현한다. 다른 말로 하면, 상속은 객체의 로직을 그대로 물려 받는 또 다른 객체를 만들 수 있는 기능을 의미한다. 단순히 물려받는 것이 아닌 기존의 로직을 수정하고 변경해서 파생된 새로운 객체를 만들 수 있게 해준다. 아래는 자바스크립트에서의 상속을 구현한 짧은 코드이다.

function Person(name) {
  this.name = name;
}
Person.prototype.name=null;
Person.prototype.introduce = function () {
  return 'My name is ' + this.name;
}
var p1 = new Person("Lee"); // My name is Lee
console.log(p1.introduce());

function Employee(name, position){ 
  this.name = name;
  this.position=position;
}

Employee.prototype = new Person();
Employee.prototype.getDetails = function() {
  return this.introduce() + ' and I work as a ' + this.position;
};

var emp = new Employee('John Doe', 'Manager');
console.log(emp.getDetails()); // My name is John Doe and I work as a Manager

Employee이라는 생성자를 만든 뒤, 이 생성자의 prototype과 Person의 객체를 연결했더니 Employee 객체도 메소드 introduce를 사용할 수 있게 되었고, 자신만의 프로퍼티도 사용할 수 있게 되었다. 그 결과 "My name is John Doe and I work as a Manager" 이 콘솔에 출력되었다. 좀더 자세히 설명하자면,

  1. Person 생성자 함수:
function Person(name) {
  this.name = name;
}
Person.prototype.name=null;
Person.prototype.introduce = function () {
  return 'My name is ' + this.name;
}
  • Person 생성자 함수는 name 인자를 받아서 this.name 속성을 설정한다.
  • Person.prototype에 name 속성을 null로 초기화하고, introduce 메서드를 정의한다. introduce 메서드는 객체의 이름을 반환하는 문자열을 생성한다.
  1. p1 객체:
var p1 = new Person("Lee"); // My name is Lee
console.log(p1.introduce());
  • new Person("Lee")를 통해 Person 생성자 함수를 호출하여 p1 객체를 생성한다.
  • p1 객체는 name 속성이 "Lee"로 설정되며, introduce 메서드를 상속받아 실행하면 "My name is Lee" 문자열을 반환한다.
  1. Employee 생성자 함수:
function Employee(name, position){ 
  this.name = name;
  this.position=position;
}
  • Employee 생성자 함수는 name과 position 두 개의 인자를 받아서 this.name과 this.position 속성을 설정한다.
  1. Employee.prototype 설정:
Employee.prototype = new Person();
  • Employee.prototype을 new Person()을 통해 Person 객체의 인스턴스로 설정한다. 이를 통해 Employee 객체는 Person 객체의 속성과 메서드를 상속받는다.
  1. getDetails 메서드:
Employee.prototype.getDetails = function() {
  return this.introduce() + ' and I work as a ' + this.position;
};
  • Employee.prototype에 getDetails 메서드를 정의한다.
  • getDetails 메서드는 introduce 메서드를 호출하여 현재 객체의 이름을 가져온 뒤, position 속성과 함께 문자열을 생성하여 반환한다.
  1. emp 객체:
var emp = new Employee('John Doe', 'Manager');
console.log(emp.getDetails()); // My name is John Doe and I work as a Manager
  • new Employee('John Doe', 'Manager')를 통해 Employee 생성자 함수를 호출하여 emp 객체를 생성한다.
  • emp 객체는 name 속성이 "John Doe"로 설정되고, position 속성이 "Manager"로 설정된다.
  • emp 객체는 Person 객체의 introduce 메서드를 상속받아 실행하면 "My name is John Doe" 문자열을 반환하며, getDetails 메서드를 실행하면 "My name is John Doe and I work as a Manager" 문자열을 반환한다.

이상의 상속과 관련하여 중요한 개념은 프로토타입(prototype)과 프로토타입 체인(prototype chain)이다. 위의 코드를 좀더 이해하기 위해선 이 두 개념에 대해 알아야 한다.

2. 프로토타입 / 프로토타입 체인

프로토타입(prototype)은 객체 지향 프로그래밍에서 객체 간의 상속과 프로퍼티 공유를 구현하기 위한 메커니즘이다.

모든 JavaScript 객체는 프로토타입을 가지며, 프로토타입은 다른 객체로써 동작할 수 있다. 프로토타입은 말 그대로 객체의 원형이라고 할 수 있다. 함수는 객체이며, 생성자로 사용될 함수도 객체이다. 객체는 프로퍼티를 가질 수 있는데 prototype이라는 프로퍼티는 그 용도가 약속되어 있는 특수한 프로퍼티이다. prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결된다. 객체는 프로토타입을 통해 프로퍼티와 메서드를 상속받고, 이를 통해 코드의 재사용성과 구조화를 촉진할 수 있다.

객체를 생성할 때, 객체 리터럴 {}이나 new 키워드를 사용하여 생성한 객체는 기본적으로 Object.prototype을 프로토타입으로 가진다. 즉, 모든 객체는 Object.prototype에 정의된 메서드와 프로퍼티를 상속받는다. 예를 들어, toString()이나 hasOwnProperty()과 같은 메서드는 Object.prototype에 정의되어 있으며, 모든 객체가 이를 사용할 수 있다.

프로토타입을 이해하기 위해 아래 예시를 보자.

function Ultra(){};
Ultra.prototype.ultraProp = true;

function Super(){}; 
Super.prototype = new Ultra();

function Sub(){};
Sub.prototype = new Super();

var o = Sub();
console.log(o.ultraProp); //true

생성자 Sub를 통해서 만들어진 객체 o가 Ultra의 프로퍼티 ultraProp에 접근 가능한 것은 prototype 체인으로 Sub와 Ultra가 연결되어 있기 때문이다. 내부적으로는 아래와 같은 일이 일어난다.

  1. 객체 o에서 ultraProp를 찾는다.
  2. 없다면 Sub.prototype.ultraProp를 찾는다.
  3. 없다면 Super.prototype.ultraProp를 찾는다.
  4. 없다면 Ultra.prototype.ultraProp를 찾는다.

프로토타입(prototype)은 객체와 객체를 연결하는 체인의 역할을 하는 것이다. 이러한 관계를 prototype chain이라고 한다

profile
즐거운 게 즐거운 것

0개의 댓글