
자바스크립트를 처음 접하게 되면 화살표 함수, 비동기에 대해서도 배우지만 생각보다 안일하게 생각하면서도 중요한 파트가 프로토타입인 것 같다.
화살표 함수, 비동기는 필수적으로 공부해야지만 자바스크립트를 다룰 수 있다면 프로토타입은 굳이 깊게 공부하지 않아도 코딩을 해온 경험과 프로토타입을 더 쉽게 사용하기 위해 나온 클래스를 사용하게 되며 눈치껏 알게되는 것 같다.
하지만 자바스크립트가 결국 프로토타입을 기반으로 한 객체지향 언어라고 하니 자세히 공부해봐야겠다.
프로토타입(prototype)은 원래의 형태 또는 전형적인 예, 기초 또는 표준이다. 개념(concept) 또는 프로세스(process)의 테스트 용도로 제작된다. '정보시스템의 미완성 버전 또는 중요한 기능들이 포함되어 있는 시스템의 초기모델'이다.
영화 터미네이터에서 나오는 T-800 이 Cyberdyne Systems Prototype Model 101 라고 불리기도 한다. 실제로 터미네이터에서는 이 기종 하나로 주인공 일행을 죽이러 과거까지 왔지만 미래에서는 해당 기종이 프로토타입을 원형으로 양산되어 쏟아지기 때문이다.
자바스크립트에서 이 프로토타입을 사용한 이유가 뭘까?
다양한 객체들 간의 공통된 특징을 클래스로 만들었던 것처럼 객체지향 프로그래밍을 위해 이 프로토타입을 사용한다.
다양한 객체들이 있을 때 이 객체들의 비슷한 특징, 상태, 함수들을 하나의 프로토타입으로 만들어서 객체지향을 구현한다.
그래서 자바스크립트는 프로토타입을 이용한 객체지향 프로그래밍 언어라고 할 수 있을 것 같다.
객체지향이란?
프로그램을 단순히 데이터와 처리 방법으로 나누는 것이 아니라, 프로그램을 수많은 '객체(object)'라는 기본 단위로 나누고 이들의 상호 작용으로 서술하는 방식이다.
객체란 '메소드, 변수'를 가지며 특정 역할을 수행하도록 인간이 정의한 추상적인 개념이다.
나무위키를 긁어오는 것은 최대한 지양하는 편이지만, 굉장히 잘 서술된 것 같다.
그런데... 다른 언어들처럼 클래스를 사용하면 되는데 굳이 왜 프로토타입일까? 라고 생각했더니
원래는 자바스크립트에 클래스가 없었기에 프로토타입으로 객체지향을 구현했지만 클래스가 추가되었다고 한다.
그래서 최신 자바스크립트, 대부분이 사용하는 타입스크립트에서도 객체지향을 위해 클래스를 사용한다고 한다.
그럼 클래스만 공부하면 되는 것 아니냐? 라고 생각했지만 자바스크립트는 프로토타입을 베이스로 만들어졌고 결국 클래스도 프로토타입을 감싸고 있는 형태이기 때문에 필수적으로 공부해야 한다.

안 이라는 객체에는 이름만 넣어줬을 뿐인데도 이름 뿐 아니라 많은 속성과 함수들이 존재한다.

그 이유는 안 이라는 인스턴스에 Object 라는 이름을 가진 프로토타입이 존재하기 때문이다.
그래서 자바스크립트에서는 객체를 생성자로 만들던, 클래스로 만들던 상관없이 Object 라는 이름의 프토로타입이 존재한다.
그래서 객체는 공통적으로 가지고 있는 속성과 함수를 묶어놓은 원형(프로토타입)을 가지고 있으며, 이 속성과 함수를 상속받아 사용할 수 있다.
왜 Object 라는 이름이라고 했냐면 아래와 같이 배열을 사용하면 Array 라는 이름의 프로토타입이 나온다.

우리가 자주사용하는 filter, find, forEach 등의 함수들이 보인다.
그리고 이 Array 프로토타입은 Object 프로토타입을 상속받는다.
위에서 작성했던 글 가장 첫 번째 문단에 Array 와 function 도 객체타입이라고 작성한 적이 있다. 아래 스크린샷에서도 확인할 수 있듯이 Array 프로토타입이 Object 프로토타입을 상속받는다.

하지만 프로토타입은 외부에서 직접 접근이 불가능하며 아래의 4가지의 경우에 접근이 가능하다.
위 스크린샷에 나와있는 __proto__
Object.getPrototypeOf()
Object.setPrototypeOf()
생성자 함수에서 prototype 이라는 속성으로 접근 가능


으로 Object 프로토타입 하나로부터 상속받을 것이므로 true로 나온다.
그럼 프로토타입을 어떻게 만들까?
먼저 아래의 사진을 보자.

위의 사진은 영화라는 생성자 함수에 이름, 나라, 설명이 들어있다.
그리고 영화1, 영화2를 만들었다.
이름, 나라 프로퍼티는 당연히 두 인스턴스가 다른 값을 가지지만, 설명이라는 메서드는 같은 값을 가지고 있다.
이렇게 항상 동일하게 들어있는 속성을 프로토타입에 넣을 수 있다.

위와 같이 프로토타입에 영화봤다를 넣어줬고, 성공적으로 만들어진 것을 확인할 수 있다.
위의 영화봤다라는 프로토타입 함수를 아래와 같이 오버라이딩 할 수도 있다.

같은 영화봤다를 사용했지만 다른 출력이 나온다.
우리는 객체를 다룰 때 Object.entries 와 같은 함수를 사용한 적이 있다. Object 라는 이름의 객체에 직접 접근해서 사용한다.
이것을 정적 메서드라고 하는데 이러한 정적 프로퍼티나 메서드는 인스턴스에서 접근할 수 없고, 클래스나 생성자의 이름으로만 접근할 수 있다.

위와 같이 "영화" 라는 생성자 이름을 이용하여 "내종목은" 이라는 정적 메서드를 등록했다.
그리고 "영화1" 이라는 인스턴스를 통해 내종목은 함수를 사용했지만 사용할 수 없었다.
오로지 "영화" 라는 생성자 이름을 통해서만 사용할 수 있다.

파란색 박스가 생성자 함수 이고, 빨간색 박스가 프로토타입에 함수를 넣는 과정이다.
초록색 박스는 인스턴스를 생성한다.
여기서 Hero 는 Human 을 아직 상속받지 않는다.
참고로 Hero 생성자 함수의 Human.call 함수는 클래스의 super() 와 같다.

위처럼 Object.create() 에 상속할 프로토타입을 전달해주면 Hero 의 인스턴스도 Human 인스턴스만 사용할 수 있던 설명() 을 사용할 수 있게된다.
굉장히 복잡해보이지만.... 클래스가 없을 때는 이렇게 생성자 함수와 프로토타입을 하나하나 지정했지만, 최신 자바스크립트에서는 클래스를 이용하여 더욱 간편하게 사용할 수 있게됐다.