Prototype

future·2021년 1월 15일
0

JavaScript

목록 보기
5/10
post-thumbnail

최신 ES6 자바스크립트에는 class 문법이 추가됐지만, class 문법이 디폴트는 아니기 때문에 자바스크립트에서는 class 대신 prototype을 사용한다. 프로토타입은 말 그대로 객체의 원형이라고 볼 수 있으며, 상속의 기능을 구현할 수 있다는 특징이 있다.

📎 Prototype Chain이란?

function Grandfather() {}
Grandfather.prototype.haircolor = 'brown';

function Father() {}
Father.prototype = new Grandfather();

function Son() {}
Son.prototype = new Father();

Father.haircolor	// 'brown'
Son.haircolor		// 'brown'

Grandfather이라는 함수를 선언하였을 때, 함수 Grandfather은 생성자(constructor) 자격을 부여받는다. 여기서 생성자란 new 키워드를 통해 다른 객체를 만들 수 있는 함수를 말한다. 또한 함수 Grandfather은 해당 함수가 생성됨과 동시에 Grandfather.prototype이라는 객체를 가지게 된다. 이 prototype을 통해 해당 객체 내에 속성이나 메서드를 추가할 수 있다.

typeof Grandfather;		// function
typeof Grandfather.prototype	// object

그리고 키워드 new를 사용하여 Grandfather로부터 Father이라는 새로운 객체를 생성하게 되면, 객체 Father은 Father.prototype이라는 객체를 가지게 되며, 객체 Grandfather.prototype의 속성을 자동으로 상속받게 된다.

Father.prototype.lastname = 'Wisley'

객체 Father.prototype에 새로운 속성을 추가해준 뒤에 똑같은 방식으로 Son이라는 객체를 Father로부터 생성했을 때, 객체 Son은 객체 Father.prototype의 속성과 더불어 Grandfather.prototype의 속성 또한 자동으로 상속받게 된다. Son은 Father로부터 생성되었지만, Father은 Grandfather로부터 생성이 되었기 때문에 최상위 객체인 Grandfather의 속성까지 모두 상속받을 수 있는 것이다.

Son.prototype.lastname;		// 'Wisley'
Son.prototype.haircolor;	// 'Brown'

Son.prototype.haircolor === Father.prototype.haircolor		// true
Son.prototype.haircolor === Grandfather.prototype.haircolor	// true

👉 이렇게 prototype으로 인해 연결된 상속관계를 Prototype Chain이라고 한다.

1) 함수는 정의되는 순간,

  • 함수를 생성한다.
  • Prototype Object(객체)를 생성한다.
    - Object의 속성으로는 constructor__proto__가 존재
    - constructor : 생성된 함수를 의미
    - __proto__ : prototype Link
  • 생성자 자격을 부여받는다.
    - new 키워드를 통해 다른 객체 생성 가능

2) new 키워드를 통해 객체가 생성되는 순간,

  • 새로 생성된 객체는 상위 함수의 Prototype Object를 가리키는 __proto__ 속성을 가지게 된다.
  • __proto__을 통해 상위 함수의 Prototype Object의 값을 참조할 수 있는 것이다.

Prototype Object는 속성을 마음대로 추가하거나 삭제할 수 있다. 그렇기 때문에 함수 Parent를 통해 새롭게 생성된 객체 child1과 child2는 Prototype Link를 통해 Parent.prototype의 속성 혹은 메서드를 참조할 수 있게 된다. 만약, 최상위 객체의 Prototype Object까지 찾아봤지만 값을 찾지 못하였을 경우에는 Undefined를 리턴하게 된다.

👉 이렇게 __proto__를 통해 상위 prototype과 연결되어 있는 상속관계를 Prototype Chain이라고 한다.

📎 Prototype을 사용하는 이유?

function Parent() {
  this.home = 'seoul';
}

const child1 = new Parent();
const child2 = new Parent();

child1.home;		// 'seoul'
child2.home;		// 'seoul'

예를 들어 2개의 객체(child1, child2)를 생성했을 때 child1과 child2는 home이라는 변수를 동일하게 가지고 있기 때문에, 객체수(2개) x 변수의 수(1개)만큼 메모리에 할당이 된다. 객체의 수가 n개까지 늘어나면 n개 * 변수의 갯수만큼 메모리에 할당이 되는 것이다.

function Parent() {}

Parent.prototype.home = 'seoul';

const child1 = new Parent();
const child2 = new Parent();

child1.home;		// 'seoul'
child2.home;		// 'seoul'

하지만 프로토타입을 사용하면 Parent.prototype 이라는 빈 객체(Object)가 생성이 되고, Parent 함수로부터 생성된 새로운 객체(child1, child2)들은 저 빈 객체(Object)에 할당되어 있는 속성들을 가져다 쓸 수 있기에 더욱 효율적이라고 볼 수 있다.

📎 new와 Object.create()의 차이

function Mufasa() {
  this.position = 'king';
}  

function Simba() {}
Simba.prototype = new Mufasa();

Simba.prototype.position	// King

Mufasa.prototype.rakecolor = 'orange';

Simba.prototype.rakecolor	// orange
  • new를 통해 객체를 생성할 경우 prototype을 이용하여 원본 주소로 찾아간다. 그렇기 때문에 하위 객체가 생성된 이후에 상위 객체에 속성을 추가/삭제한다고 해도 하위 객체의 속성 또한 자동으로 추가/삭제가 된다.
function Mufasa() {
  this.position = 'king';
}  

function Simba() {}
Simba.prototype = Object.create(Mufasa.prototype) 

Simba.prototype.position	// undefined
  • Object.create()를 통해 객체를 생성할 경우, 새로운 객체는 상위 객체의 prototype을 참조하는 것이 아닌, 상위 객체의 prototype을 prototype으로 하는 또 다른 객체에 대한 주소값을 참조하게 된다. 예시를 보았을 때, 새로 생성된 객체 Simba는 Mufasa.prototype을 참조하는 것이 아니라 Mufasa.protytpe을 prototype으로 하는 또 다른 객체를 참조한다. 한마디로 Simba가 참조하는 새로운객체의 prototype 주소와 Mufasa.prototype의 주소는 다른 주소인 셈이다.

    👉 상위 객체의 속성은 상속받으면서, 하위 객체 자신만의 속성을 추가하고 싶을 경우에는 Object.create()를 사용한다.

profile
get, set, go!

0개의 댓글