티스토리 뷰

개발공부/🟨 JavaScript

[JS] 프로토타입 (Prototype)

2023. 2. 19. 13:14

프로토타입(Prototype) 이란?

 

자바스크립트에서는 객체를 상속하기 위해 프로토타입(prototype)이라는 방식을 사용한다.

 

자바스크립트의 모든 객체들은 메서드와 속성을 상속받기 위한 템플릿으로써 프로토타입 객체(prototype object)를 가진다. 프로토타입 객체도 또 다시 상위 프로토타입 객체로부터 메서드와 속성을 상속받을 수 있고 그 상위 프로토타입 객체도 마찬가지이다.

 

이를 프로토타입 체인(prototype chain)이라 부르며, 다른 객체에 정의된 메서드와 속성을 한 객체에서 사용할 수 있도록 하는 근간이 된다.

→  상속되는 속성과 메서드들은 각 객체가 아니라 객체의 생성자의 프로토타입이라는 속성에 정의되어 있는 것이다.

 

자바스크립트에서는 객체 인스턴스와 프로토타입 간의 연결이 구성되며 이 연결을 따라 프로토타입 체인을 타고 올라가며 속성과 메서드를 탐색한다.

.

.

.

😮

위 내용이 MDN에 프로토타입을 검색해보면 나오는 프로토타입에 대한 설명인데 프로토타입이라는 개념이 처음이라 읽어도 잘 이해가 되지 않았다. 그래서 유튜브를 찾아보니 코딩애플님의 영상이 눈에 띄어서 들어보았는데 이 영상을 보고 다시 MDN 설명을 보니 prototype이 무엇인지 이해가 가기 시작했다.

 

 

Machine이라는 생성자 함수를 정의해보자.

function Machine() {
  this.q = 'strike';
  this.w = 'snowball';
}

var nunu = new Machine();

 

여기서 생성자 함수 Machine()은 부모로, nunu라는 Object는 자식으로 비유할 수 있다. (부모가 자식을 생산하는 느낌)

nunu는 부모에서 정의한 속성을 기본적으로 물려받는다.

 

그런데 여기서, prototype이라는 것을 사용해도 자식 Object에게 속성이나 메서드를 물려줄 수 있다.

나는 Machine에 prototype이라는 것을 설정해준 적이 없는데 Machine은 자동으로 prototype이라는 공간이 생긴다.

 

 

prototype은 "유전자"라고 비유해서 생각하면 이해하기 쉽다.

 

 만약 Machine의 prototype에 무언가를 추가하면 (prototype도 일종의 object이기 때문에 .~~ = ~~ 로 데이터 수정 가능)

function Machine() {
  this.q = 'strike';
  this.w = 'snowball';
}

Machine.prototype.name = 'kim';

var nunu = new Machine();

 Machine로부터 생성된 자식들은 모두 name = 'kim'을 사용할 수 있다.

아래 결과를 보면 우리는 nunu에 name을 직접 부여한 적은 없지만 부모의 유전자에 기록되어 있어서 가져다 쓸 수 있는데 이것이 prototype의 역할이다.

 

 

 

 

즉, 어떤 속성을 상속받아서 사용하고 싶다면 생성자 함수에 추가하거나, prototype에 추가하여 사용할 수 있다.

 

생성자 함수에 속성을 추가하면 자식 Object는 해당 속성을 직접 가진다.

function Machine() {
  this.q = 'strike';
  this.w = 'snowball';
}

var nunu = new Machine();

console.log(nunu);    // {q: 'strike', w: 'snowball'}

 

반면, prototype을 사용하여 속성을 추가하면 부모만 {name: 'kim'}이라는 속성을 가지고 그것을 자식이 끌어다가 쓰는 개념으로 이해할 수 있다.

Machine.prototype.name = 'kim';

console.log(nunu);       // {q: 'strike', w: 'snowball'}
console.log(nunu.name);  // 'kim'

 

위 코드에서 nunu는 직접 name이라는 속성을 가지고 있지 않은데 어떻게 부모의 name을 끌어다가 쓸 수 있는 걸까?

 

객체에서 데이터를 하나 뽑고 싶을 때 우리는 nunu.name같이 객체 뒤에 .을 사용한다.

그럼 nunu가 name을 가지고 있으면 name값을 출력한다.

 

만약 nunu가 name을 가지고 있지 않다면?

nunu의 부모 유전자, 즉 부모의 prototype을 탐색하고 거기에 name이 있다면 그 값을 출력한다.

 

위 내용을 정리해보면 자바스크립트에서 Obejct의 자료를 뽑을 때

1)  직접 자료를 가지고 있으면 그 값을 출력한다.

2)  직접 가지고 있지 않다면 부모의 prototype을 탐색하여 값이 있다면 그 값을 출력한다.

3)  부모에도 없다면 부모의 부모 prototype을 탐색

4)  그래도 없다면 또 그 부모...

 

이것이 prototype chain

 

 

 

 

 

 

그럼 Array를 다룰 때를 생각해보자.

array자료에 .sort()같은 메서드를 붙일 수 있는 이유가 무엇일까?

 

var arr = [0, 3, 1]

우리는 array를 선언할 때 보통 위와 같이 간단하게 표현하는데 컴퓨터는 내부적으로 아래와 같이 Array를 만든다.

var arr = new Array(0, 3, 1)

그럼 우리가 위에서 봤던 new Machine()과 동일한 형태인 것을 볼 수 있다.

 

Array의 부모는 prototype에 sort나 length같은 메서드들을 가지고 있기 때문에 우리가 array 자료에 그런 메서드들을 사용할 수 있는 것이다.

 

 

 

 

 

그럼 이제 prototype을 응용하는 방법을 알아보자.

만약 내가 모든 array 자료에 '2'를 삭제하는 기능을 만들고 싶고 이 기능을 자주 사용할 것 같다고 해보자.

 

내가 array자료에서 '2'를 삭제하는 함수 delete2()를 만들었고 그것을 모든 array 자료에서 쓸 수 있도록 하고 싶다면

Array.prototype.delete2 = function delete2() { ... }

위와 같이 작성하면 모든 array에서 delete2라는 함수를 사용할 수 있다.

 

실제로 아래처럼 코드를 작성해보면 delete2라는 속성이 추가된 것을 볼 수 있다.

delete3이라는 건 없으니까 에러가 난다.

 

 

 

 

 

 

 

참고 자료

🔗 [MDN]  Object prototypes

🔗 [MDN]  상속과 프로토타입

🔗 [코딩애플]  이거보고 prototype 이해 못하면 강의접음

 

 

반응형

'개발공부 > 🟨 JavaScript' 카테고리의 다른 글

[JS] 값(value)  (0) 2023.04.18
[JS] 식별자 (Identifier)  (0) 2023.04.09
[JS] 자바스크립트 비동기 처리  (0) 2023.01.29
[JS] 호이스팅 (Hoisting)  (0) 2023.01.18
[JS] 클로저 (Closure)  (0) 2023.01.09
프로필사진
개발자 삐롱히

프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그