main-logo

프로토타입

프로토타입에 대해 알아보자

profile
1320129
2023년 09월 16일 · 0 분 소요

들어가며

제가 JavaScript 처음 접했을 때는 ES6 이후에 JavaScript였습니다.
JavaScript에는 클래스가 존재했었고 객체지향에 개념을 접했을 때
객체지향은 대부분 클래스 기반이라 하여 JavaScript는 클래스 기반 언어구나!
하고 넘어갔었는데요.
하지만 프로토타입을 제대로 배우고 난 후 제 생각이 완전히 틀렸다는 걸 알게 되었습니다.
“이런 거 몰라도 작업하는데 문제없잖아”라는 생각하신 건 아니겠죠??
매우 위험한 생각이에요 지루해도 같이 공부해 보아요😊



프로토타입이란

JavaScript는 프로토타입 기반 언어입니다.
프로토타입 객체들은 직접 다른 객체로부터 속성과 메소드를 상속받습니다.
이런 방식이 바로 프로토타입 기반 상속입니다.
이는 객체 지향 언어(oop)에서 일반적으로 볼 수 있는 클래스 기반 상속과는
다른 방식의 상속을 사용한다는 것을 의미합니다.



자바스크립트에도 클래스가 존재하잖아요!

JavaScript에서는 “클래스”라는 개념이 ES6(2015) 이전에 존재하지 않았습니다!
ES6 이후에는 클래스가 추가되었지만 여전히 프로토타입 기반으로 작동을 하게 됩니다!
그 문법은 전통적인 클래스 기반이나 다른 언어에서 사용하는 문법과 비슷하여 보다 익숙한 형태를 제공하기 위한 ‘문법적 설탕’(syntactic sugar)이라고 생각합니다.

image1.gif

 



그래서 어떻게 작동하는 거예요?

JavaScript는 객체가 생성될 때, 그 객체의 “프로토타입”은 특정 다른 객체를 참조합니다.
이렇게 참조된 다른 객체가 바로 그 객체의 “부모” 역할을 하는 것입니다.
예시 코드같이 확인해 보아요!

const Items = [1, 2, 3, 4];

Items.map();
Items.sort();
Items.foreach();

해당 코드는 배열을 작업할 때 자주 쓰이는 메소드들 입니다.
하지만 우리는 해당 기능을 만들어준 적이 없는데요.😳

아까 설명드린 부모한테 상속을 받아 사용할 수 있게 된 거랍니다.
여기서 “부모” 역할은 배열(Array) 인스턴스의 Array.prototype 객체입니다.

JavaScript에서 배열 메소드인 sort(), map(), forEach() 등은 모두 Array.prototype에 정의된 메소드입니다.
이런 방식으로 JavaScript는 코드 재사용성을 높이고, 개발자가 쉽게 공유된 기능(메소드)들을 활용할 수 있도록 해줍니다!(너무 편하게 잘 쓰고 있어…)
이제는 mdn에서 설명하는 Array.prototype.메소드 가 무슨 뜻인지 이제는 이해가 잘 되시겠죠?

 

image2.png


(메소드 검색할 때마다 mdn에서 prototype이 왜 붙는 거지 항상 궁금했었거든요!)

프로토타입 체인

JavaScript에서 모든 객체는 프로토타입 체인을 통해 특정 프로토타입 객체를 상속받습니다!
이 체인은 결국 최상위 객체인 Object.prototype으로 끝나게 됩니다.
이런 관계 때문에 자식 객체가 부모 객체의 속성이나 메소드에 접근하려고 하면, JavaScript 엔진은 먼저 해당 이름의 속성이나 메소드가 자식 객체 자체에 있는지 확인합니다!
만약 없다면, 엔진은 프로토타입 체인을 따라 위쪽으로 올라가며 해당 이름의 속성이나 메소드를 찾습니다.

따라서 만약 부모 객체에 해당 속성/메소드가 있다면, 자식 객체에서도 마치 자신의 것처럼 사용할 수 있게 됩니다. 스코프 체인이랑 비슷한데요~!
예시 코드를 한번 볼까요??

function 재료() {
  this.달걀 = true;
  this.고기 = true;
}

function 전처리() {
  this.삶은달걀 = true;
  this.익은고기 = true;
}

function 샐러드() {
  this.드레싱 = true;
}

function 스테이크() {
  this.스테이크소스 = true;
}

전처리.prototype = new 재료();
샐러드.prototype = new 전처리();
스테이크.prototype = new 전처리();

console.log(스테이크.prototype);

 

image3.png

 

위 코드에서 우선 재료, 전처리, 샐러드, 스테이크라는 네 가지 함수를 정의하였습니다!
해당 함수들은 앞에 new를 붙여 생성자 함수입니다.
재료 함수는 달걀과 고기라는 속성을 가진 객체를 생성합니다.

그다음으로 전처리 함수가 있습니다. 여기서 주목할 점은, 전처리. prototype이 new 재료()로 설정되었다는 것입니다.
이렇게 함으로써 “전처리” 객체가 “재료” 객체의 속성을 상속받게 됩니다.
재료를 손질할 수 있게 되겠네요!

마찬가지로, ‘샐러드’와 ‘스테이크’ 객체도 ‘전처리’ 객체에서 상속받은 속성 외에도 추가적으로 ‘재료’ 객체에서 상속받은 속성까지 사용할 수 있게 됩니다.
마지막 줄에서 출력된 결과를 보면, 스테이크에는 직접적으로 스테이크 소스 만 있는 것 같지만 실제로는 그 위의 프로토타입 체인을 통해 익은 고기, 달걀 등과 같은 속성들을 추가적으로 가지고 있음을 알 수 있습니다!
레시피를 전체적으로 다 볼수가 있네요!

마치며

매일 출근하면서 사용했던 JavaScript를 완전 잘못 생각하고 있었습니다.
기초 개념 지식이 왜 중요한지 다시 한번 느껴지는 내용이었습니다!
긴 글 읽어주셔서 감사합니다!