TIL_PROTOTYPE

김진경·2020년 3월 21일
0

IM19

목록 보기
4/21

자바스크립트에는 다른 언어들(Java, Python, Ruby)에는 있는
Class 개념 대신 Prototype이 존재한다.

아래의 코드를 한번 보자.

function Person() {
  this.eyes = 2;
  this.nose = 1;
}

var kim  = new Person();
var park = new Person();

console.log(kim.eyes);  // => 2
console.log(kim.nose);  // => 1
console.log(park.eyes); // => 2
console.log(park.nose); // => 1

위 코드는 한가지 단점이 있다.
kim, park 외의 다른 객체(new Person();)이 늘어날 수록 eyes, nose 도 늘어나
메모리를 많이 쓴다는 것.

이런 단점을 아래처럼 Prototype으로 해결할 수 있다.

function Person() {}

Person.prototype.eyes = 2;
Person.prototype.nose = 1;
// person 안에 있던 eyes, nose를 밖으로 꺼내 Prototype 형식으로 작성했다.
var kim  = new Person();
var park = new Person():

console.log(kim.eyes);  // => 2
console.log(kim.nose);  // => 1
console.log(park.eyes); // => 2
console.log(park.nose); // => 1
  1. Person.prototype 이라는 빈 객체에 eyes와 nose를 저장시킨다

  2. Person으로부터 파생된 kim, park는 Person.prototype에서 eyes, nose를 꺼내 쓴다.

따로 Person.prototype에 eyes, nose를 저장시켰기 때문에 kim,park 외의 새로운 객체가 늘어나도 더 이상 메모리가 늘어나지 않는다.

자바스크립트에서 Prototype은 기본적으로 Object와 Link로 구성되어있다. 그중 먼저 Object를 알아보자.

Prototype Object


코드를 작성하다 보면 객체를 생성하는 일은 자주 있을 것이다. 그런데 그 객체들이 전부 '함수'로부터 생성되었다는 것을 알고 있는가?

function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성
  1. 함수가 정의되고

  2. 그 함수로 객체를 생성한다.

만약 그렇다면 함수를 정의하지 않고 객체를 생성하면?

var obj = {}

위 코드의 어딜 봐도 함수가 없지만 사실 위 코드는 다음과 같다.

var obj = new Object();


(new Object()는 {}이다. )

빈 객체를 생성해도 자바스크립트에서 기본적으로 제공하는 Object 라는 함수에서
객체를 생성해 제공하는 것이다.

그런데 이 때, 정의된 함수가 객체를 생성할 때 동시에 2가지 일을 더한다.

1. 정의된 함수는 생성자(constructor)자격이 생긴다.

생성자(constructor)자격이 생기면 new 키워드를 통해 객체를 만들어낼 수 있다.
생성자 자격이 있는 함수만이 new 키워드를 사용할 수 있다.

(객체는 불가능하다)

2. 정의된 함수의 Prototype Object 생성 및 연결

함수가 정의되면, Prototype Object도 같이 생성된다.

(abc.prototype이라는 객체가 생성되었다)

위의 예시를 보면 abc라는 함수를 만들자,
abc.prototype이라는 객체가 같이 생성된 모습을 보인다.

constructor라는 키 값에 함수 abc라는 밸류값이 들어있고,
__proto__라는 키 값에 Object라는 밸류값이 들어있다.

여기서 abc.prototype은 객체이기 때문에 속성을 마음대로 추가할 수 있다.

abc.prototype이라는 객체에 eyes라는 속성을 추가했고 밸류로 2를 넣은 모습이다.
그리고 abc()는 생성자 함수이기 때문에 new 키워드를 사용할 수 있다.
그렇게 kim이라는 새로운 객체는 eyes라는 속성을 abc.prototype에서 가져와 사용할 수 있다.

그런데 어떻게 kim은 eyes라는 속성도 없으면서 2라는 값을 가져와 사용할 수 있을까?
그건 Prototype Link 덕분이라고 할 수 있다.

kim을 콘솔창에서 찍어보면 빈 객체가 나올 것이라고 생각하는가? 자바스크립트의 모든 객체가 가지고 있는 딱 하나의 속성이 있다. _proto_.

생성자 함수만 가지고 있던 prototype 속성과 달리 _proto_ 속성은 어느 객체나 가지고 있다.

(kim.prototype은 나오지 않지만 _proto_는 출력된다.)

kim이 eyes와 nose 속성을 가질 수 있었던 이유는 _proto_가 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리키기 때문이다. 여기서는 abc.prototype을 가리킬 것이다.

(역시 abc 함수의 prototype을 가리키고 있었다)

kim객체가 eyes를 직접 가지고 있지 않기에 eyes 속성을 찾을 때 까지 상위 프로토타입, 그것의 상위 프로토타입... 계속 탐색해 나간다. 최상위인 Object의 Prototype Object까지 도달했는데도 못찾았을 경우 undefined를 리턴한다. 이렇게 _proto_속성을 통해 상위 프로토타입과 연결되어있는 형태를 프로토타입 체인(Chain)이라고 한다.

이런 프로토타입 체인 구조 때문에 모든 객체는 Object의 자식이면서,
Object Prototype Object에 있는 모든 속성을 사용할 수 있다.

profile
Maktub.

2개의 댓글

comment-user-thumbnail
2020년 3월 22일

es5 부터는 JS 에서도 클래스를 사용할 수 있답니당 !
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes

1개의 답글