Javascript 클래스 정복(1) 프로토타입

주니·2021년 12월 21일
1

js문법

목록 보기
3/3

자바스크립트를 공부하고 노드JS와 리액트를 배우고 있는 중이지만, 부끄럽게도 아직 정확히 이해하지 못 한 자바스크립트 문법이 몇 가지 있다.
그 중 나의 골머리를 썩게 하는 클래스! MDN의 클래스 문서를 해석하고 정리하는 과정을 통해서 클래스를 정복해보자.!!

Class란?

Class는 객체를 생성하기 위한 템플릿입니다. 클래스는 데이터와 이를 조작하는 코드를 하나로 추상화합니다. 자바스크립트에서 클래스는 프로토타입을 이용해서 만들어졌지만 ES5의 클래스 의미와는 다른 문법과 의미를 가집니다.

이하의 내용은 이 분의 포스트를 거의 카피한 수준입니다. 제 글보다 이 분 글을 읽는 것이 더 좋아요~~!
https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

엥..? 그럼 프로토타입은 뭐지?

Javascript는 클래스라는 개념이 없다.(클래스를 공부하는데 모순되는 말이긴 하다. 사실 자바스크립트는 프로토타입 기반 언어였고 클래스라는 개념이 없었다. 최근에 사용의 편의를 위해 클래스 형태를 도입했다고 생각하는것이 좋다.) 그래서 기존의 객체를 복사하여 새로운 객체를 생성하는 프로토타입 기반의 언어이다.

위의 함수와 객체들은 공통적으로 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이란 객체(인스턴스가 더 정확하겠다.)에도 eyes와 nose가 저장되어있고, park에도 eyes와 nose가 저장되어 있을 것이다. 그럼 메모리는 총 4개가 할당될 것이다. 객체를 100개 만들면 200개의 변수가 메모리에 할당되는 문제가 생길 것이다.!

function Person() {}
Person.prototype.eyes = 2;
Person.prototype.nose = 1;
var kim  = new Person();
var park = new Person():
console.log(kim.eyes); // => 2

Person.prototype이라는 빈 Object가 어딘가에 존재하고, Person 함수로부터 생성된 객체(kim, park)들은 어딘가에 존재하는 Object에 들어있는 값을 모두 갖다쓸 수 있습니다.
eyes와 nose를 어딘가에 있는 빈 공간에 넣어놓고 kim과 park이 공유해서 사용하는 것이다. 이로인해 불필요한 메모리생성을 막을 수 있는 것이다.

위의 내용을 정확히 이해 못 하겠다고 하더라도(내가 그렇다) 확실한 것은 프로토타입이란 개념이 불필요한 메모리 낭비를 막는 하나의 방법으로서 공유라는 방식을 사용하기 위해 도안된 것을 기억해야 한다.

프로토타입은 Prototype Link와 Prototype Object를 통틀어 일컫는 개념이다.
하나 씩 살펴보자.

Prototype Object

객체는 언제나 함수로 생성된다.!! 매우 생소하다. 적어도 나에게는 그렇다.
필자에게 익숙한 객체 생성 방법은 아래와 같다.

const obj = {};
const obj = new Object();

아! 이것을 보면 new Object()를 통해 객체를 생성하니 객체는 함수로 생성되는 것을 볼 수 있다.

function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성

실제로 이와 같은 형태로 객체가 생성될 수 있다. 위에서 항상 사용했던 방식이기도 하다. 이와 마찬가지로 함수, 배열도 모두 함수로 정의되어 있다.

이것이 Prototype Object와 무슨 상관이 있느냐?
함수가 정의될 때는 2가지 일이 동시에 이루어진다.

1. 해당 함수에 Constructor(생성자) 자격부여
Constructor 자격이 부여되면 new를 통해 객체를 만들어 낼 수 있게 됩니다. 이것이 함수만 new 키워드를 사용할 수 있는 이유입니다.

function SoccerPlayer() { 
  this.position = "Forward";
}
var VanPersie = new SoccerPlayer();
VanPersie.position;
// "Forward"

이렇게 말입니다. 객체 생성에 목적이 있는 함수가 아니라고 하더라도 constructor 자격이 부여됩니다.

2. 해당 함수의 Prototype Object 생성 및 연결


함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성이 됩니다.

Person.prototype 부분을 보면 생성된 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있습니다. Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor와 proto를 가지고 있습니다.
constructor는 Prototype Object와 같이 생성되었던 함수를 가리키고 있습니다. [[prototype]] 는 Prototype Link입니다. 밑에서 자세히 설명합니다. 이제 위에서 kim과 park이 나왔던 예제를 다시 보겠습니다.

자, 이제 보이지 않던 새로운 것이 보이기 시작한다. 위에서 Person.prototype 객체에 저장한 eyes, nose들이 저장된 것을 위의 사진을 통해 확인할 수 있다. 그 다음 Person이란 생성자 함수를 통해 만들어진 kim이란 객체를 콘솔 찍어보면 Person 함수의 prototype과 연결된 것을 확인할 수 있다. 이렇게 연결되어 있기에 kim.eyes를 호출하게 되면
kim->Person.prototype->eyes를 찾게되는 것이다. 아직 잘 이해가 안 되는 것은 당연하다. 밑의 Prototype Link를 보게 되면 더욱 잘 이해가 될 것이다.


자, 이걸 다시 보게되면 kim의 객체에서는 eyes라는 속성이 존재하지 않는다. 하지만 kim.eyes를 실행하면 2라는 값을 참조하는 것을 볼 수 있다. 이것이 가능한 단 한 가지 이유는 [[prototype]]속성이다! 이것이 Person Prototype Object에 접근하게 해주는 다리 역할을 해주는 것이다.

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

이런 프로토타입 체인 구조 때문에 모든 객체는 Object의 자식이라고 불리고, Object Prototype Object에 있는 모든 속성을 사용할 수 있습니다. 한 가지 예를 들면 toString함수가 있겠습니다.

## 마무리
위의 내용을 정리하면서 왜 자바스크립트가 정말 프로토타입 언어라고 하는지 알 수 있었다. 우리가 간단히 사용하던 많은 메소드들이 어떻게 구성되었었는지 확인할 수 있었는 개념이 아닌가 싶다. 자바스크립트의 구조에 대해 이 개념을 통해 다른 분들도 한 발자국 나아갈 수 있었으면 좋겠다. 끝으로 다음 포스트에서 프로토타입을 활용한 class에 대해 더 다루어 보도록하겠다.

<참조> 이 분 게시글을 거의 카피한 수준입니다. 자세한 글의 내용은 이분 포스트를 참고해주세요!!
https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

profile
달팽이처럼

0개의 댓글