본문 바로가기

Javascript

자바스크립트 Prototype

반응형

자바스크립트 공부를 하면서 제일 많이 어려워했던 부분을 꼽으라하면 난 무조건 프로토타입을 꼽을 것 같다 🥲. 처음 프로토타입을 공부했을 당시에는 헷갈리는 프로퍼티들과 머릿속으로 잘 그려지지 않는 구조로 인해 많이 어려워했다. 그리고 무엇보다 '나는 프로토타입을 사용하지도 않는데, 이걸 왜 공부해야하지?'라고 생각했다.

 

그런데 이런 생각들은 최근 프로토타입 공부를 하며 싹 바뀌었다. 그리고 다음의 목록으로부터 많은 도움을 받았다.

 

1. 내가 언제 프로토타입을 사용했는지 살펴보기

2. 코어 자바스크립트 06.프로토타입 읽기

3. 프로토타입의 삼각형 구조(밑에 나옴)를 바탕으로 이해하기

난 언제 프로토타입을 썼을까? 🤔

먼저 자바스크립트 개발자가 프로토타입을 언제 사용하는지 알아보자. 분명히 모든 개발자들이 처음부터 프로토타입을 사용했을거라 확신한다!

 

가장 기본적인 예시로는 배열이 있다.(사실 자바스크립트의 모든 객체에서 사용했을 것이다.)

 

const arr = [1, 2, 3]; 
console.log(arr); // [1, 2, 3]

arr.push(4);
console.log(arr); // [1, 2, 3, 4]

arr.pop();
console.log(arr); // [1, 2, 3]

 

위 코드에서 잘 생각해보면, 우리가 정의한 내용은 arr이라는 배열 뿐이다. 우리는 arr이라는 배열에 push(), pop() 메소드를 정의한 적은 없다. 하지만 다들 개발하면서 당연스럽게 사용했을 메소드들이다.

 

'arr는 배열이니깐 기본 Array가 가진 메소드는 당연히 쓸 수 있지!!'라고 생각했을 텐데...그래서 왜 arr은 Array의 내장 메소드들을 당연하게 사용할 수 있었을까???? 바로 지금부터 알아볼 prototype 덕분이다 🤩

 

추가로 mdn의 Array파트를 보면 다음처럼 인스턴스 메서드라고 해놓고 prototype이 포함되어있는 것을 알 수 있다.(난 왜 이전까지 이 생각을 못했을까?)

 

 

아마 우리는 정말 많은 곳에서 프로토타입의 원리를 활용하여 개발했을 것이다.

프로토타입

자바스크립트는 프로토타입 기반 언어이다. 자바와 같은 클래스 기반 언어는 '상속'을 사용하지만, 프로토타입 기반 언어는 어떤 원형 객체를 참조함으로써 상속과 비슷한 효과를 얻는다.

 

프로토타입 기반 언어는 class없이 객체를 생성할 수 있는데, ES6 이후 class 문법이 추가 되어 자바스크립트에서도 class를 통해 객체를 생성할 수 있다.

 

프로토타입의 개념을 그림으로 표현하면 다음과 같다.

 

 

위 그림의 특징을 설명하면 다음과 같다.

 

  • Constructor를 new 연산자와 함께 호출하면 instance가 생성됩니다.
  • 이 instance에는 __proto__프로퍼티가 자동 부여됩니다.
  • __proto__ 프로퍼티는 Constructor.prototype을 참조합니다.
  • Constructor의 prototype 프로퍼티인 프로토타입 객체는 constructor 프로퍼티를 통해 다시 Constructor로 접근 가능한다.

prototype은 객체다.

 

자바스크립트는 함수에 자동으로 객체인 prototype 프로퍼티를 생성한다. 이때 해당 함수를 생성자 함수로서(new 연산자와 함께) 사용할 경우, 그로부터 생성된 인스턴스에는 __proto__ 프로퍼티가 자동으로 생성되고, 이 프로퍼티는 생성자 함수의 prototype을 참조한다. __proto__ 프로퍼티는 생략하여 사용 가능하다.

 

따라서 생성자 함수의 prototype에 어떤 메서드나 프로퍼티가 있다면, 인스턴스에서도 마치 자신의 것인마냥 (사실은 __proto__ 프로퍼티가 생략된 것)해당 메서드나 프로퍼티를 사용할 수 있다.

프로토타입 체인

어느 생성자 함수의 프로토타입 객체던지 간에 프로토타입 객체는 말 그대로 **객체(**Object)다. 따라서 객체인 프로토타입 내부에는 또 다시 __proto__ 속성이 존재하고, 기본적으로 모든 객체의 __proto__는 Object.prototype과 연결되어 있다.

 

const arr = [1, 2, 3, 4, 5];

 

위처럼 선언된 arr라는 배열의 내부 구조는 다음과 같다.

 

 

이처럼 어떤 데이터의 __proto__프로퍼티 내부에 다시 __proto__프로퍼티가 연쇄적으로 이어지는 형태를 프로토타입 체인이라고 한다. 그리고 이 체인을 따라가면 어떤 메서드나 프로퍼티를 검색하는 것을 프로토타입 체이닝이라고 한다.

메서드 오버라이딩

만약 instance가 프로토타입과 같은 이름의 메서드나 프로퍼티를 가지고 있는 상황이면 어떻게 될까?

 

결과부터 말하자면, 인스턴스의 메서드와 프로퍼티를 부른다. 이를 메서드 오버라이딩이라고 한다.

 

자바스크립트 엔진은 프로토타입 체이닝에 의해 하나의 메서드를 찾기 위해 가장 가까운 대상인 자신의 프로퍼티를 검색하고, 없으면 그 다음으로 가까운 대상인 __proto__에 있는 메서드를 검색한다. 따라서 둘 다에 같은 이름의 메서드가 있다면 본인에게 있는 메서드를 사용한다.

그렇다고 해서 프로토타입의 메서드가 없어지는 건 아니다. 메서드 오버라이딩의 경우에는, 첫번째 메서드가 있고 그 위에 똑같은 이름이지만 다른 역할을 하는 메서드를 얹는다고 생각하면된다. 아예 갈아끼우는게 아니다.

 

참고

코어자바스크립트 6장 프로토타입

 

반응형

'Javascript' 카테고리의 다른 글

자바스크립트 Strict mode  (1) 2021.09.24
자바스크립트 Hoisting  (0) 2021.09.19
함수 선언문 vs 함수 표현식  (0) 2021.04.27
DOM  (0) 2021.04.27
자바스크립트 This  (0) 2021.04.27