개발 기술/개발 이야기

프로토타입 (feat. 매운 맛🔥)

by GicoMomg (Lux) 2021. 11. 4.

이 포스팅은 프로토타입 객체, 링크, 프로퍼티에 대한 설명은 물론, 이제까지 우리가 알고 있던 프로토타입 개념이 사실과 조금 다를 수 있다는 매운맛 정보가 담겨있습니다. (사실 안 매워용..ㅎㅎ)


1. 프로토타입 (feat. 매운 맛🔥)

자바스크립트는 프로토타입 기반 언어라고 불린다. 그런데 이 프로토타입은 무엇이며 어떻게 생성될까?
이 포스팅에서 자세히 알아보자 🙂

1) 프로토타입이란?

(1) 프로토타입은 무엇일까

  • 자바스크립트에서는 객체를 생성할 때, 원형을 복사하는 방식을 취한다. (ex. new Object())
  • 그리고 이 과정에서 객체에 프로토타입이 추가되는데, 우리는 프로토타입을 통해 객체 원형의 정보에 접근할 수 있게 된다.
  • 만약 A객체를 기반으로 B객체를 생성했다면, B객체에서는 A객체의 정보에 접근할 수 있다는 말이다.
  • A객체에 test()가 있다면 B객체에서는 이 메소드를 접근해 사용할 수 있다.
  • 간단한 설명은 이 정도로 하고 예시와 함께 살펴보자!

(2) 프로토타입은 어떤 형태일까

  • 아래 코드는 Object()를 사용해 obj 객체를 만드는 모습이다.
const obj = new Object(); 

  • obj객체를 출력해보면 프로토타입([[Prototype]])이 존재한다.


  • obj의 원형인 Object에서는 hasOwnProperty()가 있는데, obj는 프로토타입이 존재하므로,
  • 이 프로토타입을 이용해 해당 함수에 접근할 수 있다.


그런데 앞서 본, 프로토타입 이미지를 보니, constructor, proto가 있던데, 이건 무엇일까?

이 두 개를 설명하기 위해서는 프로토타입 객체, 프로토타입 링크을 알아야 한다! 한 번 알아보자~



2) 프로토타입 객체? 프로토타입 링크?

(1) 프로토타입 객체

"프로토타입 객체는 자식에게 물려줄 정보를 담고 있다."

  • 아래 코드는 Animal객체를 이용해 dog인스턴스를 만든 모습이다.
  • 이 2줄에는 프로토타입 객체, 링크가 관여하는데 이 과정을 그림과 함께보자.
class Animal {}
const dog = new Animal();

  1. Animal()을 이용해 dog인스턴스를 생성하고자 한다.


  1. Animal()을 사용해 dog인스턴스를 만든다.
    이 과정에서 Animal의 정보가 담긴 프로토타입 객체가 관여하는데, 각각 Animaldog에 연결된다.


dog 인스턴스 생성 후 dog, dog의 원형과 연결된 프로토타입 객체는 무엇일까?

  • 앞서 언급했듯이 js에서는 객체 생성시 원형 복사 방식을 취하며, 생성된 객체는 원형(부모) 정보를 가진다.
  • 그렇다면 생성 객체는 부모의 어떤 정보를 가지고 있는 걸까?
  • 그 정보는 바로 프로토타입 객체이다.

Animal 클래스 입장에서 보자!

  • Animal클래스 입장에서 봤을 때, Animal은 항상 자신을 복사하여 자식 객체(dog)를 만든다.
  • 그리고 자식 객체에게 정보를 상속시켜주기 위해 프로토타입 객체를 가지게 된다.
  • 이 말은, 프로토타입 객체생성될 객체(자식)가 참조할 값을 지칭한다고 볼 수 있다.
  • 결국, 모든 객체는 원형(부모)이 소유한 프로토타입 객체를 기반으로 생성된다.

아니 잠시만요? 그림을 보니까 __proto__가 프로토타입과 연결되어 있던데 이건 뭐죠?


(2) 프로토타입 링크

"프로토타입 링크(__proto__)는 원형(상위)과의 연결고리 역할을 한다"

  • 그림에서 dog인스턴스의 __proto__프로토타입 객체constructor가 연결되어 있다.


그런데 이 __proto__는 어떤 역할을 하며, 왜 constructor와 연결된걸까?

  • 우리는 자식 객체에서 원형(부모)의 속성, 메소드를 접근할 수 있음을 알고 있다.
  • 그럼 자식이 부모에게 접근하는 방법이 필요한 것이 아닌가? 그 방법은 __proto__를 사용하는 것이다.

  • 아래 그림은 Animaltest()가 있다고 가정하고, dog에서 test()를 찾는 과정을 나타냈다.

  • dog에서 test()를 호출하고자 한다. 하지만 dog에는 해당 함수가 존재하지 않는다.


  • dog는 부모의 정보를 접근하여 test()가 있는지 확인하고 싶다.
  • 이때 바로 __proto__를 이용해 부모의 정보에 접근하는 것이다.


  • 그런데 왜 프로토타입 객체가 아닌 constructor와 연결된 걸까?
  • 그 이유는 construcutor가 생성자 함수이기 때문이다.
  • 이 생성자 함수에는 dog를 만들 때, Animal을 기반으로 dog에서 사용할 정보를 생성한다.
  • 그러므로 test()에 접근하기 위해서는 construcutor와 연결되어야 한다.



3) 내가 알던 프로토타입 개념과 다른데?

아니 잠시만요! 프로토타입 객체와 링크에 대해 알겠어요. 그런데, 제가 알고 있는 프로토타입은 객체에서 기본적으로 제공할 속성, 메소드를 저장한 공간인데요? 이상해요!

네! 이상할 수 있습니다. 왜냐하면 그 개념은 프로토타입 프로퍼티에 대한 설명이기 때문이죠!
대부분 프로토타입이라고 알고 있는 그 개념은 프로토타입 프로퍼티에 대한 설명입니다 🙂


(1) 사실 그건 프로토타입 프로퍼티 얘기!

  • 프로토타입 객체의 constructor프로토타입 프로퍼티가 있다.
  • 프로토타입 프로퍼티자식에게 물려줄 속성을 말한다.
  • 자식 객체는 부모의 메소드, 속성에 접근할 수 있는데, 그 이유는 프로토타입 프로퍼티에 그 정보가 담겨 있기 때문이다.
  • 결국, 프로토타입 프로퍼티로 인해 자식은 부모의 속성, 메소드를 사용할 수 있게 된다.



4) 프로토타입 예시를 보자

(1) 프로토타입 프로퍼티 예시

  • Animal 클래스는 name속성을 가지고 있는데,
  • 이 속성은 프로토타입 프로퍼티로서, 자식 객체에게 상속되는 값이 된다.
class Animal {
  constructor({ name }) {
    this.name = name;      // 하위에게 물려줄 속성(prototype property)
  }
}

  • 만약 이 Animal 클래스를 사용해 dog객체를 생성한다면 dog에서 name을 사용할 수 있다.


(2) 프로토타입 링크 예시

  • 앞선 예시를 다시 이용해보자.
class Animal {
  constructor({ name }) {
    this.name = name;    
  }
}
const dog = new Animal({ name: 'dog' });

  • __proto__프로토타입 링크이며, dog객체를 만들 때 사용한 원형에 대한 연결이다.
  • dog객체의 프로토타입 링크를 사용해 age속성을 추가하고, age값을 12로 하면 어떻게 될까?
dog.__proto__.age = 12;

  • 이 경우 age 속성이 추가되며, 값 또한 할당되어 있다.
  • 이처럼 우리는 프로토타입 링크(__proto__ )를 사용해 속성을 추가할 수 있게 된다.

(단, 기존에 존재하는 속성값을 프로토타입 링크로 수정할 수 없음)


오늘 우리는 프로토타입 객체, 링크, 프로퍼티에 대해 알아보았다.
프로토타입 객체는 생성될 객체(자식)가 참조할 값이며 프로토타입 링크는 상위와의 연결,
마지막으로 프로토타입 프로퍼티는 자식에게 물려줄 속성이다.
사실 개발을 할 때 프로토타입을 자주 사용하지는 않지만 (모듈을 만든다면 모를까) 개념정도는 알아두면 좋을 듯하다.




참고자료

반응형

댓글