1. 프로토타입이란 무엇인가
자바스크립트는 클래스 기반 언어(C++, Java)와 달리
프로토타입 기반(Prototype-based) 언어다.
즉, 모든 객체는 다른 객체를 상속(prototype link) 받아서 동작한다.
“모든 객체는 자신의 부모 역할을 하는 원형(Prototype)을 가진다.”
const user = { name: "기범" };
console.log(user.__proto__); // Object.prototype
✅ 모든 객체는 내부적으로 __proto__ (또는 [[Prototype]])를 갖는다.
✅ 이걸 통해 상위 객체의 속성과 메서드를 참조할 수 있다.
2. 프로토타입 체인(Prototype Chain)
프로토타입 체인은 상속의 연결 고리다.
자바스크립트는 객체의 프로퍼티를 찾을 때 다음 순서로 탐색한다.
1️⃣ 객체 자신
2️⃣ 상위 프로토타입 (__proto__)
3️⃣ 최상위 Object.prototype
4️⃣ 없으면 undefined 반환
const user = { name: "기범" };
console.log(user.toString()); // [object Object]
✅ toString()은 user 객체에 없음
✅ 따라서 상위 Object.prototype 에서 찾는다
3. 함수와 프로토타입의 관계
모든 함수는 생성자 함수가 될 수 있다.
즉, new 키워드로 호출하면 프로토타입을 기반으로 한 객체가 만들어진다.
function User(name) {
this.name = name;
}
User.prototype.sayHi = function () {
console.log(`안녕, 나는 ${this.name}`);
};
const kb = new User("기범");
kb.sayHi(); // 안녕, 나는 기범
✅ kb는 User의 인스턴스
✅ User.prototype에 정의한 메서드는 모든 인스턴스가 공유한다.
4. 인스턴스 구조 시각화
function User(name) {
this.name = name;
}
User.prototype.sayHi = function () {
console.log(`Hello, ${this.name}`);
};
const kb = new User("기범");
구조:
kb (인스턴스)
│
└── __proto__ → User.prototype
│
└── __proto__ → Object.prototype
✅ kb.sayHi()를 호출하면 자바스크립트는 다음 순서로 탐색한다.
1️⃣ kb 자체에 sayHi가 있는가? → 없음
2️⃣ User.prototype에 있는가? → 있음 → 실행
5. 프로토타입 체인의 끝
모든 프로토타입 체인의 끝에는 Object.prototype이 있다.
그 위에는 아무것도 없다.
console.log(Object.prototype.__proto__); // null
즉, 자바스크립트의 모든 객체는 궁극적으로 Object를 상속받는다.
6. 프로토타입 상속 확장
기존 객체를 확장하고 싶을 때도 프로토타입을 활용할 수 있다.
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function () {
console.log(`${this.name}이(가) 움직인다`);
};
function Dog(name) {
Animal.call(this, name); // 부모 생성자 호출
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function () {
console.log(`${this.name}이(가) 짖는다`);
};
const choco = new Dog("초코");
choco.move(); // 초코이(가) 움직인다
choco.bark(); // 초코이(가) 짖는다
✅ Object.create()를 통해 상위 프로토타입을 복제
✅ constructor를 다시 지정해야 올바른 참조 유지
7. 클래스(Class)와의 관계
ES6 이후 등장한 class 문법은 사실 프로토타입의 문법적 설탕(syntactic sugar) 이다.
class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`안녕, ${this.name}`);
}
}
const kb = new User("기범");
kb.sayHi();
위 코드는 내부적으로 이렇게 변환된다 👇
function User(name) {
this.name = name;
}
User.prototype.sayHi = function () {
console.log(`안녕, ${this.name}`);
};
✅ 클래스 내부의 메서드는 전부 prototype에 저장된다.
✅ 즉, 클래스도 결국 “프로토타입 상속” 위에서 돌아간다.
8. Object.create()로 직접 프로토타입 지정
Object.create()는 특정 프로토타입을 가진 객체를 직접 생성할 수 있다.
const animal = {
move() {
console.log("움직인다");
},
};
const dog = Object.create(animal);
dog.bark = function () {
console.log("멍멍!");
};
dog.move(); // 움직인다
dog.bark(); // 멍멍!
✅ dog.__proto__ === animal
✅ 상속 구조를 수동으로 만드는 가장 직관적인 방법
9. 프로토타입 확장의 위험성
프로토타입을 직접 수정하면 전역적인 부작용이 생길 수 있다.
Array.prototype.remove = function (value) {
const index = this.indexOf(value);
if (index > -1) this.splice(index, 1);
};
const arr = [1, 2, 3];
arr.remove(2);
console.log(arr); // [1, 3]
겉보기엔 편리하지만,
모든 배열에서 remove가 생기기 때문에
다른 코드나 라이브러리와 충돌할 수 있다.
✅ 그래서 내장 객체의 prototype 수정은 절대 금지!
10. 프로토타입 체인 확인
function User() {}
const kb = new User();
console.log(kb.__proto__ === User.prototype); // true
console.log(User.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
이 세 줄이 프로토타입 체인의 모든 걸 설명한다.
11. instanceof 연산자
instanceof는 객체의 프로토타입 체인을 검사한다.
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
const choco = new Dog();
console.log(choco instanceof Dog); // true
console.log(choco instanceof Animal); // true
console.log(choco instanceof Object); // true
✅ instanceof는 객체의 실제 클래스보다 “프로토타입 체인”을 기준으로 판별한다.
12. 실무 예제 — 커스텀 객체 시스템
function Person(name) {
this.name = name;
}
Person.prototype.introduce = function () {
console.log(`안녕하세요, 저는 ${this.name}입니다.`);
};
function Developer(name, skill) {
Person.call(this, name);
this.skill = skill;
}
Developer.prototype = Object.create(Person.prototype);
Developer.prototype.constructor = Developer;
Developer.prototype.code = function () {
console.log(`${this.name}은 ${this.skill}로 개발 중...`);
};
const kb = new Developer("기범", "React");
kb.introduce(); // 안녕하세요, 저는 기범입니다.
kb.code(); // 기범은 React로 개발 중...
✅ 생성자 + 프로토타입 상속으로 클래스 구조를 구현
✅ ES5 시절 클래스형 설계 패턴의 전형적인 형태
13. 프로토타입의 장점
장점 설명
| ✅ 메모리 절약 | 메서드를 인스턴스마다 복제하지 않음 |
| ✅ 상속 구현 가능 | Object.create, __proto__ 활용 |
| ✅ 동적 확장 가능 | 런타임에 메서드 추가 가능 |
| ✅ 클래스 문법보다 유연 | 함수형 + 객체형 모두 표현 가능 |
14. 정리
항목 요약
| Prototype | 객체의 원형(부모 객체) |
| Prototype Chain | 상속 구조 |
| 함수의 prototype 속성 | 인스턴스가 참조하는 공유 메서드 공간 |
| __proto__ | 객체의 내부 프로토타입 링크 |
| 클래스 문법 | 프로토타입 기반의 문법적 설탕 |
| 주의점 | 내장 객체 prototype 수정 금지 |
15. 마무리
프로토타입을 이해하면
자바스크립트의 “객체지향 구조”가 완전히 눈에 보이기 시작한다.
this, 클로저, 프로토타입 —
이 세 가지가 맞물릴 때, 비로소 자바스크립트를 진짜 언어로 이해할 수 있다.
“클로저가 함수의 기억이라면,
프로토타입은 객체의 유전자다.”
'frontend > javascript' 카테고리의 다른 글
| 🟨 2-21. 비동기 프로그래밍 완전정복 — Promise, async/await, 그리고 이벤트 루프의 협업 구조 (0) | 2025.11.07 |
|---|---|
| 🟨 2-20. 자바스크립트 클래스(Class) 내부 구조 — 문법적 설탕 이상의 진짜 의미 (0) | 2025.11.07 |
| 🟨 2-18. 클로저(Closure) 완전 정복 — 함수형 자바스크립트의 핵심 개념과 실무 응용 (0) | 2025.11.07 |
| 🟨 2-17. this 완전 정복 — 함수, 객체, 클래스에서의 this 바인딩 규칙과 혼동 포인트 (0) | 2025.11.07 |
| 🟨 2-16. 자바스크립트 이벤트 루프와 콜스택 — 비동기 코드의 진짜 실행 순서 이해하기 (0) | 2025.11.07 |