들어가며
javascript 는 프로토타입 기반 객체지향 프로그래밍 언어이다.
프로토타입이 뭘까?
Prototype의 의미
중복으로 사용되는 곳이 너무 많아 정리한다
1. 일반 공학에서의 prototype : 최종 제품을 만들기 전에 만든 초기 시험 모델(시제품)
2. C언어에서의 함수 prototype : 함수를 정의하기 전에 컴파일러에게 함수의 이름, 반환형, 매개변수 타입을 미리 알려주는 선언
3. javascript의 prototype : 객체가 다른 객체의 속성과 메서드를 상속받기 위해 연결하는 상위 객체 참조
이 글에서는 3번만 얘기할거니까 헷갈리지 말자
표현을 정리하자면, 프로토타입 패턴이라는 것은 객체를 생성하는 방법을 다루는 디자인 패턴을 뜻한다.
Javascript의 객체
객체라 함은 메모리에 저장되는 일련의 데이터 덩어리라고 생각하면된다.
자바스크립트는 모든 것이 객체(object)라는 설계철학을 가지고있다.
함수도 객체, 배열도 객체, 문자열도 객체 전부 다 객체이다.
자바스크립트에서 모든 인스턴스들(함수, 배열, 문자열 인스턴스들) 은 생성되는 순간, 부모의 객체 메모리 주소 값을 자신의 내부 포인터인 [[Prototype]]에 저장한다.
따라서 자바스크립트의 모든 객체 인스턴스들은 Object.prototype을 조상으로 갖는다.
아래 구조(prototype chain)로 구성되어있는 것이다.
obj
└── [[Prototype]] → parent
└── [[Prototype]] → Object.prototype

여기서 __proto__는 객체의 내부 prototype ( [[Prototype]] )에 접근하는 getter/setter
obj.__proto__ 는 실제로 obj.[[Prototype]]
여기서 .constructor는 해당 prototype을 만든 생성자 함수. (어떤 객체가 어떤 생성자에서 왔는가?)
String.prototype.constructor === String
Array.prototype.constructor === Array
Function.prototype.constructor === Function
Object.prototype.constructor === Object
생성자 함수? -> 객체를 만들기 위한 함수
function Dog(name) {
this.name = name;
}
const d = new Dog("puppy");
여기서 Dog이 생성자 함수다.
Javascript의 객체 생성
전통적인 클래스 기반 언어(C++, Java)는 인스턴스를 만들 때 새로운 메모리 덩어리를 찍어내지만, 자바스크립트는 복사하지 않고 클래스간 연결만 한다.
연결이란? 객체가 생성되는 순간 부모가 될 다른 객체의 메모리 주소값을 자신의 [[Prototype]] 포인터에 저장하는 것
직접 객체 생성하기 (new없이)
const parent = { gold: 100 };
const child = Object.create(parent); // child -> parent 연결
- parent 객체 생성: 메모리 주소 0x111에 생성. 내부에 gold: 100이 저장
- child 객체 생성: 메모리 주소 0x222에 생성. 내부 데이터는 비어있음
- 연결 : Object.create()는 새 객체를 만들면서 그 객체(child)의 [[Prototype]]을 원하는 객체(parent)로 직접 지정하는 함수 child 객체의 헤더 영역에 있는 [[Prototype]] 필드에 0x111이라는 주소가 기록됨
child
├─ own properties: (없음)
└─ [[Prototype]] ──> parent
├─ gold: 100
└─ [[Prototype]] → Object.prototype
child.__proto__ === parent
위와 같은 형태로 객체가 생성되며 ECMAScript spec(자바스크립트 표준) 에서 Object.create(proto)의 동작은 아래의 알고리즘이다.
1. 새로운 빈 객체 O 생성
2. O.[[Prototype]] = proto
3. O 반환
Javascript Delegation
내가 어떤 데이터나 함수를 가지고 있지 않을 때, 내 메모리에 저장된 주소를 타고 상위 객체(prototype에 연결되어있는 객체)의 메모리 영역으로 이동해서 그 데이터를 빌려오는 것이다.
아까 Object.create로 객체를 생성했을때를 생각해보자.
1. child 객체(0x222) 자체에서 gold 찾기
2. 없으면 child.[[Prototype]] → parent
3. parent (0x111)에서 gold 발견 → 100 반환
new의 동작
이런식으로 new 를 이용하면 prototype을 연결하는 것 뿐만 아니라, constructor를 실행한다.
| 방식 | prototype 연결 | constructor 실행 |
| new | O | O |
| Object.create() | O | X |
const d = new Dog("puppy");
javascript에서 new를 이용해 객체를 생성하면 엔진 내부에서 아래와 같은 순서로 실행된다.
객체 생성 -> prototype 연결 -> constructor 실행 -> 객체 반환
//1. 빈 객체 생성
{}
//2. prototype 연결
obj.[[Prototype]] = Dog.prototype
//3. constructor 실행
Dog.call(obj, "puppy")
//4. 객체 반환
return obj
사실상 아래와 같은 함수가 동작하는 거다
function fakeNew(constructor, ...args) {
const obj = Object.create(constructor.prototype);
constructor.apply(obj, args);
return obj;
}
이 과정을 거쳐서 최종적으로 아래 구조를 갖는 객체가 탄생한다.
d
├─ name: "puppy"
└─ [[Prototype]] → Dog.prototype
Prototype 상속
자바스크립트에서 상속이란 (prototype 기반 상속) 특정 인스턴스의 [[Prototype]] 포인터를 상위 객체를 가리키게 설정하는 것을 의미한다.
class Dog extends Animal {}
Dog.prototype.__proto__ = Animal.prototype
자바 스크립트에도 class라는 키워드는 있지만 이건 그냥 Syntactic Sugar(사람 눈에만 예뻐보이는 문법) 라고 한다.
굳이 Syntactic Sugar라고 말하는 이유는 C++이나 자바 같은 prototype기반 언어가 아닌 경우 class를 선언하는 것은 실제로 해당 타입을 만드는 개념이다.
즉, C++과 JAVA와 같은 프로그래밍 언어의 상속은 class와 class 간의 type hierarchy의 개념이고
Javascript 에서의 상속은 object와 object 간의 prototype delegation의 개념이다.
┌──────────────┐
│ 배열 arr1 │ ┐
├──────────────┤ │
│ length: 0 │ │ arr1 객체
│ [[Prototype]]:──┼─→ 같은 메모리 주소 가리킴
└──────────────┘ │
│
┌──────────────┐ │
│ 배열 arr2 │ │
├──────────────┤ │
│ length: 0 │ │ arr2 객체
│ [[Prototype]]:──┼─→ (같은 Array.prototype)
└──────────────┘ │
│
↓ 모두 가리키는 곳
┌────────────────────┐
│ Array.prototype │ (하나만 메모리 존재)
├────────────────────┤
│ push: function │
│ pop: function │
│ slice: function │
│ ...배열 메서드들 │
└────────────────────┘
이제 아래를 완벽히 이해할 수 있다.
Object.prototype.toTest = function () { return 'test1' }
console.log( "abc".toTest() );
// "test1"
function fn () {}
fn.prototype.name = 'test2'
var newFn = new fn();
console.log(newFn.name)
// "test2"
console.log(newFn.toTest());
// "test1"
출처 : Javascript는 프로토타입 기반 언어이다
왜 이러는 거???
이런 식으로 특정한 객체가 반복되어 인스턴스로 생성되면 딱 한번만 생성하고 이후부터는 생성된 객체를 복사해서 쓰자 라는 관점으로 접근하는 것이 프로토타입 패턴
// 이건 너무 객체 생성 비용이 높으니까...
Player evan = new Player();
Player john = new Player();
Player wilson = new Player();
// 이런 방법으로 접근해보는 것은 어떨까?
Player player = new Player();
Player evan = player.clone();
Player john = player.clone();
Player wilson = player.clone();
출처 : https://evan-moon.github.io/2019/10/23/js-prototype/
참고
'공부 > JUN STUDY' 카테고리의 다른 글
| JavaScript Object Property Lookup이란 (자바 스크립트 객체가 property를 찾는 순서) (0) | 2026.03.04 |
|---|---|
| 2026 다시 쓰는 컴파일러 vs 인터프리터 (인터프리터의 동작 원리에 대해) (0) | 2026.02.11 |
| 인간은 프로그램의 동작을 완벽하게 이해할 수 있을까 (1) (5) | 2025.08.12 |
| node.js 서버 항상 켜두기 (pm2 사용방법) (0) | 2025.01.17 |
| L* Algorithm(L star Algorithm) 이란? - 개념/예제/이해하기 (1) | 2024.10.30 |