자바스크립트를 이해해보자 (4)

손성호·2025년 6월 11일

이번에 알아볼 개념은 '프로토타입'입니다. 자바스크립트에서 프로토타입은 무엇인지, 왜 나왔는지에 대해 작성해보겠습니다.

What is 프로토타입

흔히들 자바스크립트를 프로토타입기반의 언어라고 합니다.
그럼 여기서 프로토타입기반이란 무엇일까요?
프로토타입기반 프로그래밍은 객체지향 프로그래밍의 한 형태입니다.
다만 클래스가 없고, 클래스가 없으니 상속하는 것이아닌 객체를 원형(프로토타입)으로 하여 복제해 사용하는 방식입니다.
그래서 프로토타입기반을 클래스리스(class-less)라고 부르기도합니다.
프로토타입 기반 언어는 자바스크립트외에도 루아,R이 있습니다.

Why Using 프로토타입

모든 자바스크립트 객체는 [[Prototype]]이라는 hidden 속성을 갖습니다.
이 값은 null이거나 다른 객체에 대한 참조(포인터)가 됩니다. 다른객체를 참조하는 경우 참조 대상을 프로토타입이라 부릅니다.
만약 원형객체를 참조하는 객체가 있을경우, 프로토타입을 통해 원형객체의 속성에 접근할 수 있습니다.
여기서 [[Prototype]]은 숨겨진 프로퍼티지만, __proto__변수 혹은 Object.create(proto)메소드를 이용해 값을 정해줄 수 있습니다.
Object.create(proto) 메소드의경우 인자로 원하는 프로토타입을 넣으면 이를 프로토타입으로한 객체를 반환해줍니다.
비슷한 메소드로 Object.setPrototypeOf()가 있지만, 런타임에 프로토타입 객체를 설정하는것이라 성능상 안좋다고 합니다. (권장하지 않음)


//방법 1
let a = {name : 'son'};
let b = {age : 27};
b.__proto__ = a;

//방법 2
let a = {name : 'son'};
let b = Object.create(a);
b.age = 27;

  
console.log(b.name); // son
console.log(b); // {age: 27}

proto변수, Object.create()메소드를 이용해 b의 prototype을 a로 설정했습니다.
확인해보니 b변수에서 name속성을 가지고있는 것 처럼보입니다.
그렇지만 b변수를 로그찍어보면 b는 처음에 정의한 age속성만 가지고 있는걸 확인 할 수 있습니다.
사실은 b에서 프로토타입을 통해 타고올라가 b가 name을 가지고 있는 것 처럼 사용한 것이죠.
이렇게 프로토타입에서 상속받은 속성을 '상속 프로퍼티'라고 합니다.
프로토타입을 통해 마치 class에서 상속을 받은것 마냥 사용할 수 있게된거죠.

How 프로토타입 동작방식

프로로타입도 왜 객체지향형인지 느낌이 오시나요?
조금 더 실용적인 예시를 보여드리겠습니다.

let animal = {
  walk() {alert('걸어요')}
};
let rabbit = {
  jump() {alert('뛰어요')}, 
  __proto__ : animal
};
let giantRabbit = {weight: 20, __proto__ : rabbit};

giantRabbit.walk();
giantRabbit.jump();
console.log(giantRabbit); // {weight:20}

여기선 두번 연결된 형태입니다.
giantRabbit의 프로토타입은 rabbit이고 rabbit의 프로토타입은 animal인 상황입니다.
마치 체인으로 연결된 형태라해서 이를 프로토타입 체이닝이라고 합니다.

프로토타입 체이닝엔 세가지 제약사항이 있습니다.

    1. 순환참조는 허용되지 않는다.
    1. proto의 값은 객체나 null만 가능하다다.
    1. 객체엔 오직 하나의 [[Prototype]]만 있을 수 있다.

3번의 경우 자바같은 객체지향언어에선 다중상속이 금지되어있지만, c++에선 다중상속이 가능합니다. (다이아몬드 상속)
역시 자바를 따라만들어서 그런지.. 다중상속은 막혀있네요

또한 당연하게도, 상속받은 객체를 건드려도 원형객체엔 영향이 가지 않습니다.
프로토타입은 속성을 읽을때만 사용되기 때문이죠.
속성을 수정하려면(추가,삭제) 원본객체에 직접 해야 합니다.

let animal = {age : null};
let rabbit = {__proto__ : animal};
rabbit.age = 20;

console.log(rabbit.age) // 20;
console.log(animal.age) // null;

이건 얼핏보면 animal객체의 age속성을 바꾼 것처럼 보이지만?
rabbit객체의 age속성을 바꾼 것입니다.
객체 하나를 만들고 여기에 메서드를 많이 구현해 놓은 다음, 여러 객체에서 이 커다란 객체를 상속받게 하는 경우가 많기 때문에 이런 특징을 잘 알아두셔야 합니다. 상속받은 메서드를 사용하더라도 객체는 프로토타입이 아닌 자신의 상태를 수정합니다.

정리

이렇게 자바스크립트의 프로토타입에 대해 알아보았습니다.

정리하자면

  • 자바스크립트는 프로토타입 기반 언어이다.
  • 프로토타입 기반언어는 객체지향형 언어이고 class-less라고 부르기도한다.
  • 프로토타입을 통해 마치 class의 상속받은 것처럼 속성을 사용할 수 있다.
  • 프로토타입은 읽기전용이며, 하나만 설정할 수 있다.

2025.06.18 - Object메소드들 추가

출처

모던 자바스크립트

위키백과

MDN Object.setPrototypeOf

MDN Object.create

profile
사용자를 위한 웹화면을 개발하고 있습니다.

2개의 댓글

comment-user-thumbnail
2025년 6월 15일

빅토르 잘 보고갑니다 : )

1개의 답글