프로토타입과 상속
객체의 프로토타입 체인이 속성과 메서드를 찾는 과정을 추적하고 생성자 상속과 class 문법의 내부 원리를 연결합니다.
대부분의 객체 지향 언어는 클래스(Class) 기반으로 상속을 구현합니다.
반면 자바스크립트는 ES6 이전까지 클래스 개념 없이 프로토타입(Prototype) 메커니즘으로 상속을 구현해 왔습니다.
이를 프로토타입 기반 상속(Prototype-based Inheritance)이라고 합니다.
class 키워드가 도입된 지금도, 자바스크립트의 객체 지향은 여전히 내부적으로는 프로토타입을 기반으로 동작합니다.
따라서 자바스크립트 개발자라면 class 문법 뒤에 숨겨진 프로토타입의 원리를 정확히 이해하는 것이 필수적입니다.
프로토타입 동작을 이해하면 class 문법과 라이브러리 내부 동작을 해석하기 쉬워집니다.
이번 장에서는 프로토타입 개념, 상속 동작 방식, class 키워드와 프로토타입의 관계를 정리합니다.
프로토타입 (Prototype): 객체의 상속 연결
자바스크립트 객체는 프로토타입 객체와 연결되어 속성·메서드를 상속받을 수 있습니다. 프로토타입이 null이면 더 이상 연결된 객체가 없으며, 프로토타입 체인은 여기서 끝납니다.
이 연결된 객체를 프로토타입(Prototype)이라고 부릅니다.
객체는 자신의 프로토타입으로부터 속성과 메서드를 상속받을 수 있습니다.
객체에서 어떤 속성이나 메서드를 찾을 때, 자바스크립트 엔진은 먼저 그 객체 자신에게 해당 속성이 있는지 확인합니다.
만약 없다면, 그 객체의 프로토타입으로 이동하여 찾습니다.
프로토타입에도 없다면, 다시 그 프로토타입의 프로토타입으로 이동하여 찾는 과정을 반복합니다.
이 연쇄적인 연결을 프로토타입 체인(Prototype Chain)이라고 합니다.
내부 슬롯과 접근자 프로퍼티
일반 객체는 [[Prototype]]이라는 숨겨진 내부 슬롯(internal slot)을 가집니다.
이 [[Prototype]] 값은 프로토타입 객체 또는 null을 가리킵니다.
개발자는 __proto__ 접근자 프로퍼티(getter/setter)를 통해 이 [[Prototype]] 슬롯에 간접적으로 접근할 수 있습니다.
이 접근자는 오래된 코드에서 볼 수 있지만 새 코드는 Object.getPrototypeOf()를 사용하세요. __proto__라는 자체 속성이 가려 버리거나, 프로토타입이 null인 객체에 접근자가 없을 수 있기 때문입니다. 아래 원래 예시의 __proto__는 연결을 설명하기 위해 남겨 두며, 확인용으로는 함께 적힌 표준 API를 사용합니다.
const user = {
name: "김민준",
age: 28
};
// user 객체의 프로토타입을 확인합니다.
// 브라우저 환경에서는 일반적으로 Object.prototype이 출력됩니다.
console.log(user.__proto__);
// 또는 더 표준적인 방법: Object.getPrototypeOf(user)
console.log(Object.getPrototypeOf(user));
// user는 Object.prototype의 toString 메서드를 상속받아 사용합니다.
console.log(user.toString()); // 결과: [object Object]
// user 객체 자체에는 toString 메서드가 없지만, 프로토타입 체인을 통해 Object.prototype.toString을 찾아서 사용합니다.생성자 함수와 prototype 프로퍼티
아래 Person처럼 일반 생성자 함수는 인스턴스의 프로토타입으로 사용할 prototype 프로퍼티를 가집니다. 모든 함수가 이 프로퍼티를 가지는 것은 아니며, 화살표 함수나 일반 메서드 등은 구분해야 합니다.
이 prototype 프로퍼티는 해당 함수가 생성자 함수(Constructor Function)로 사용될 때, 이 함수가 생성할 인스턴스(Instance) 객체들의 프로토타입이 될 객체를 가리킵니다.
function Person(name, age) {
this.name = name;
this.age = age;
}
// Person 함수의 prototype 객체에 sayHello 메서드를 추가합니다.
Person.prototype.sayHello = function() {
console.log(`안녕하세요, 제 이름은 ${this.name}입니다.`);
};
const person1 = new Person("이수민", 25);
const person2 = new Person("박지훈", 30);
// person1과 person2는 Person의 인스턴스이며,
// 이들의 [[Prototype]]은 Person.prototype을 가리킵니다.
console.log(person1.__proto__ === Person.prototype); // 결과: true
console.log(person2.__proto__ === Person.prototype); // 결과: true
// 인스턴스들은 자신에게 sayHello 메서드가 없지만, 프로토타입 체인을 통해 접근합니다.
person1.sayHello(); // 결과: 안녕하세요, 제 이름은 이수민입니다.
person2.sayHello(); // 결과: 안녕하세요, 제 이름은 박지훈입니다.
// 각 인스턴스는 sayHello 메서드를 복사한 것이 아니라,
// 프로토타입 객체의 동일한 메서드를 참조합니다.
console.log(person1.sayHello === person2.sayHello); // 결과: true이러한 방식으로 메서드를 프로토타입에 정의하면, 모든 인스턴스가 동일한 메서드를 공유하게 되어 메모리를 효율적으로 사용할 수 있습니다.
this.sayHello = function() { ... }처럼 생성자 안에서 만들면 인스턴스마다 새 함수가 생깁니다. 동일한 동작을 공유한다면 프로토타입 메서드가 적합하고, 인스턴스마다 별도 클로저를 유지해야 한다면 개별 함수가 필요할 수 있습니다.
constructor 프로퍼티
일반 생성자가 처음 만든 prototype 객체에는 생성자를 가리키는 constructor 프로퍼티가 있습니다.
이 값은 바꾸거나 상속받을 수 있으므로 모든 객체의 생성자를 항상 정확히 식별할 수 있다는 보장은 아닙니다.
function Animal(name) {
this.name = name;
}
console.log(Animal.prototype.constructor === Animal); // 결과: true
const dog = new Animal("바둑이");
console.log(dog.constructor === Animal); // 결과: true이 예시에서는 수정되지 않은 기본 constructor를 통해 Animal을 찾습니다. 앞서 설명했듯 속성을 바꿀 수 있으므로 신뢰할 수 있는 생성 이력이나 유형 검사로 일반화하지 않습니다.
상속: 프로토타입 체인의 활용
자바스크립트의 상속은 이 프로토타입 체인을 통해 이루어집니다.
한 객체가 다른 객체의 프로토타입이 되고, 그 객체는 또 다른 객체의 프로토타입이 되는 식으로 연결되어, 마치 사슬처럼 이어지는 구조입니다.
프로토타입 체인을 이용한 속성/메서드 검색
프로토타입 속성 탐색 사슬 — 상태 추적
자체→첫/다음 prototype에서 존재 검사 후 처음 발견한 곳에서 멈춘다. 같은 key/current object/검색 결과를 추적하면 own undefined와 없는 key를 구분한다.
LOOKUP · ORDINARY OBJECT
프로토타입 탐색: 찾은 지점에서 멈춘다
일반 객체의 속성 읽기는 자신의 속성을 먼저 검사한다. 없을 때만 [[Prototype]]을 따라가며, 어느 단계에서든 발견하면 탐색을 끝낸다.
- Instance own property
요청한 key가 있으면 즉시 읽는다. data property는 저장된 값, accessor는 getter 결과다.
- Type.prototype
없을 때만 [[Prototype]]으로 이동한다. 여기서 발견해도 즉시 읽고 끝난다.
- Object.prototype
이 예시의 다음 프로토타입이다. 여기서도 없을 때만 다음 연결로 이동한다.
- 끝까지 없고 다음이 null
undefined를 반환한다. null 자체는 검사할 속성 노드가 아니다.
- 없으면 다음 [[Prototype]]
- 발견하면 조기 종료
Shadowing은 앞에서 발견한 같은 key가 가리는 것
own property의 값이 undefined여도 그 속성은 존재하므로 다음 프로토타입으로 넘어가지 않는다. Type.prototype → Object.prototype → null은 예시 체인이다. 사용자 정의 상속이나 null prototype 객체는 연결이 다르다.
이 예의 조건
- 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
- 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
- 원래 본문의 구현과 도표가 설명한 설계 보강을 분리한다. 서사에 포함한 확장 동작은 assumptions에 명시하고 이미 구현된 안전장치로 주장하지 않는다.
관계도의 보충 설명
| 구분 | 내용 |
|---|---|
| 전체 관계·조건 설명 | 자체 속성, 첫 프로토타입, 다음 프로토타입을 차례로 검사한다. 각 질문의 있음 가지는 값을 읽고 끝나며 없음만 다음 객체로 간다. 마지막 연결이 null이면 없는 속성의 결과는 undefined이다. 값이 undefined인 자체 속성도 있음 가지로 끝난다. 실제 체인 길이는 객체에 따라 다르다. |
| 원도표 조건·주석 | Instance own property: 요청한 key가 있으면 즉시 읽는다. data property는 저장된 값, accessor는 getter 결과다. |
| 원도표 조건·주석 | Type.prototype: 없을 때만 [[Prototype]]으로 이동한다. 여기서 발견해도 즉시 읽고 끝난다. |
| 원도표 조건·주석 | Object.prototype: 이 예시의 다음 프로토타입이다. 여기서도 없을 때만 다음 연결로 이동한다. |
| 원도표 조건·주석 | 끝까지 없고 다음이 null: undefined를 반환한다. null 자체는 검사할 속성 노드가 아니다. |
| 원도표 설명 | Shadowing은 앞에서 발견한 속성이 뒤의 같은 key를 가리는 것 |
| 장면 | 현재 관찰값 | 설명 | 변화 이유 |
|---|---|---|---|
| own key 검사 | own key: 있음/없음 / 값: undefined도 존재 가능 | 찾는 key가 객체 자신의 속성인지 확인한다 | 값 undefined와 key 부재는 다르다 |
| own이면 종료 | 결과: own undefined / prototype: 검색 안 함 | 자신의 undefined를 찾았어도 탐색을 끝낸다 | 부모의 같은 이름 값으로 대체하지 않는다 |
| 없으면 prototype | 현재: 다음 prototype / 종료: 찾음 또는 null | own이 없을 때만 chain에서 같은 key를 찾는다 | prototype lookup은 부재 조건에서만 이어진다 |
프로토타입 속성 탐색 사슬 — 상태 추적
자체→첫/다음 prototype에서 존재 검사 후 처음 발견한 곳에서 멈춘다. 같은 key/current object/검색 결과를 추적하면 own undefined와 없는 key를 구분한다.
LOOKUP · ORDINARY OBJECT
프로토타입 탐색: 찾은 지점에서 멈춘다
일반 객체의 속성 읽기는 자신의 속성을 먼저 검사한다. 없을 때만 [[Prototype]]을 따라가며, 어느 단계에서든 발견하면 탐색을 끝낸다.
- Instance own property
요청한 key가 있으면 즉시 읽는다. data property는 저장된 값, accessor는 getter 결과다.
- Type.prototype
없을 때만 [[Prototype]]으로 이동한다. 여기서 발견해도 즉시 읽고 끝난다.
- Object.prototype
이 예시의 다음 프로토타입이다. 여기서도 없을 때만 다음 연결로 이동한다.
- 끝까지 없고 다음이 null
undefined를 반환한다. null 자체는 검사할 속성 노드가 아니다.
- 없으면 다음 [[Prototype]]
- 발견하면 조기 종료
Shadowing은 앞에서 발견한 같은 key가 가리는 것
own property의 값이 undefined여도 그 속성은 존재하므로 다음 프로토타입으로 넘어가지 않는다. Type.prototype → Object.prototype → null은 예시 체인이다. 사용자 정의 상속이나 null prototype 객체는 연결이 다르다.
이 예의 조건
- 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
- 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
- 원래 본문의 구현과 도표가 설명한 설계 보강을 분리한다. 서사에 포함한 확장 동작은 assumptions에 명시하고 이미 구현된 안전장치로 주장하지 않는다.
관계도의 보충 설명
| 구분 | 내용 |
|---|---|
| 전체 관계·조건 설명 | 자체 속성, 첫 프로토타입, 다음 프로토타입을 차례로 검사한다. 각 질문의 있음 가지는 값을 읽고 끝나며 없음만 다음 객체로 간다. 마지막 연결이 null이면 없는 속성의 결과는 undefined이다. 값이 undefined인 자체 속성도 있음 가지로 끝난다. 실제 체인 길이는 객체에 따라 다르다. |
| 원도표 조건·주석 | Instance own property: 요청한 key가 있으면 즉시 읽는다. data property는 저장된 값, accessor는 getter 결과다. |
| 원도표 조건·주석 | Type.prototype: 없을 때만 [[Prototype]]으로 이동한다. 여기서 발견해도 즉시 읽고 끝난다. |
| 원도표 조건·주석 | Object.prototype: 이 예시의 다음 프로토타입이다. 여기서도 없을 때만 다음 연결로 이동한다. |
| 원도표 조건·주석 | 끝까지 없고 다음이 null: undefined를 반환한다. null 자체는 검사할 속성 노드가 아니다. |
| 원도표 설명 | Shadowing은 앞에서 발견한 속성이 뒤의 같은 key를 가리는 것 |
| 장면 | 현재 관찰값 | 설명 | 변화 이유 |
|---|---|---|---|
| own key 검사 | own key: 있음/없음 / 값: undefined도 존재 가능 | 찾는 key가 객체 자신의 속성인지 확인한다 | 값 undefined와 key 부재는 다르다 |
| own이면 종료 | 결과: own undefined / prototype: 검색 안 함 | 자신의 undefined를 찾았어도 탐색을 끝낸다 | 부모의 같은 이름 값으로 대체하지 않는다 |
| 없으면 prototype | 현재: 다음 prototype / 종료: 찾음 또는 null | own이 없을 때만 chain에서 같은 key를 찾는다 | prototype lookup은 부재 조건에서만 이어진다 |
객체에서 속성이나 메서드에 접근하려고 할 때, 다음과 같은 순서로 검색이 진행됩니다.
객체 자신에서 검색: 가장 먼저 해당 속성이나 메서드가 객체 자체에 직접 정의되어 있는지 확인합니다.
프로토타입 체인 상위로 이동: 만약 객체 자신에게 없으면, [[Prototype]]이 가리키는 부모 객체(프로토타입)로 이동하여 거기서 다시 해당 속성을 찾습니다.
반복: 이 과정을 프로토타입 체인의 끝(일반적으로 Object.prototype의 null 프로토타입)에 도달할 때까지 반복합니다.
undefined 반환: 체인의 끝까지 도달했는데도 찾지 못하면, undefined를 반환합니다.
const parent = {
parentProp: "Parent Value",
parentMethod: function() {
console.log("Parent Method Called!");
}
};
const child = {
childProp: "Child Value"
};
// child의 프로토타입을 parent로 설정합니다.
// Object.setPrototypeOf()는 객체의 [[Prototype]]을 설정하는 표준적인 방법입니다.
Object.setPrototypeOf(child, parent);
console.log(child.childProp); // 결과: Child Value (child 객체 자신의 속성)
console.log(child.parentProp); // 결과: Parent Value (프로토타입 체인을 통해 parent에서 찾음)
child.parentMethod(); // 결과: Parent Method Called! (프로토타입 체인을 통해 parent에서 찾음)
console.log(child.nonExistent); // 결과: undefined (체인 끝까지 찾았으나 없음)생성자 함수를 이용한 상속 (고전적인 방식)
ES6 class 문법이 도입되기 전에는 주로 생성자 함수와 프로토타입을 조합하여 상속을 구현했습니다.
// 부모 생성자 함수
function Animal(name) {
this.name = name;
this.species = "동물";
}
Animal.prototype.sound = function() {
console.log("동물 소리!");
};
// 자식 생성자 함수
function Dog(name, breed) {
// Animal 생성자를 호출하여 name과 species를 상속받습니다.
// call() 메서드를 사용하여 this를 Dog의 인스턴스로 바인딩합니다.
Animal.call(this, name); // 상위 생성자의 속성 상속
this.breed = breed;
}
// Dog.prototype을 Animal.prototype의 새로운 객체로 설정하여 프로토타입 체인을 연결합니다.
// Object.create()는 지정된 프로토타입을 가진 새로운 객체를 만듭니다.
Dog.prototype = Object.create(Animal.prototype);
// constructor 참조를 Dog로 되돌립니다. 프로토타입 상속 자체에 필수인 단계는 아닙니다.
Dog.prototype.constructor = Dog;
// Dog.prototype에 Dog만의 메서드를 추가합니다.
Dog.prototype.bark = function() {
console.log("멍멍!");
};
const myDog = new Dog("댕댕이", "시바견");
console.log(myDog.name); // 결과: 댕댕이 (Animal에서 상속받은 속성)
console.log(myDog.species); // 결과: 동물 (Animal에서 상속받은 속성)
console.log(myDog.breed); // 결과: 시바견 (Dog 자신의 속성)
myDog.sound(); // 결과: 동물 소리! (Animal.prototype에서 상속받은 메서드)
myDog.bark(); // 결과: 멍멍! (Dog.prototype 자신의 메서드)
console.log(myDog.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
console.log(Animal.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true (체인의 끝)여기서 Animal.call(this, name)은 현재 인스턴스에 name·species라는 자체 속성을 작성합니다. Object.create(Animal.prototype)은 메서드를 찾을 프로토타입 연결을 만듭니다. 둘은 역할이 다릅니다. 원래 코드 주석의 “속성 상속”은 부모 생성자 코드를 재사용해 초기화한다는 뜻이며, name을 부모 프로토타입에서 읽는다는 뜻은 아닙니다.
class 키워드: 문법적 설탕
ES6(ECMAScript 2015)부터 자바스크립트에 class 키워드가 도입되었습니다.
이는 기존의 프로토타입 기반 상속을 더 익숙한 객체 지향 언어의 클래스 문법처럼 보이도록 하는 문법적 설탕(Syntactic Sugar)입니다.
즉, class 키워드를 사용해도 내부적으로는 여전히 프로토타입 기반으로 동작합니다.
class 선언 및 인스턴스 생성
// 부모 클래스
class Animal {
constructor(name) {
this.name = name;
this.species = "동물";
}
sound() { // 이 메서드는 Animal.prototype에 추가됩니다.
console.log("동물 소리!");
}
}
// 자식 클래스 (extends 키워드를 사용하여 상속)
class Dog extends Animal {
constructor(name, breed) {
super(name); // 부모 클래스의 constructor를 호출합니다. (필수)
this.breed = breed;
}
bark() { // 이 메서드는 Dog.prototype에 추가됩니다.
console.log("멍멍!");
}
// 부모 메서드 오버라이딩 (재정의)
sound() {
console.log(`${this.name}는 멍멍 짖습니다!`);
}
}
const myCat = new Animal("나비");
myCat.sound(); // 결과: 동물 소리!
const myNewDog = new Dog("초코", "푸들");
console.log(myNewDog.name); // 결과: 초코
console.log(myNewDog.species); // 결과: 동물
console.log(myNewDog.breed); // 결과: 푸들
myNewDog.sound(); // 결과: 초코는 멍멍 짖습니다! (오버라이딩된 메서드)
myNewDog.bark(); // 결과: 멍멍!
// 내부적으로 여전히 프로토타입 체인으로 연결되어 있습니다.
console.log(myNewDog.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
console.log(Animal.prototype.__proto__ === Object.prototype); // trueclass 클래스명 { ... }: 클래스를 선언합니다.constructor(매개변수): 인스턴스가 생성될 때 호출되는 특별한 메서드입니다. 여기서 인스턴스의 속성을 초기화합니다.- 메서드:
constructor외에 정의된 함수들은 해당 클래스의prototype객체에 추가됩니다. extends 부모클래스: 다른 클래스를 상속받을 때 사용합니다.super(): 자식 클래스의constructor내부에서 부모 클래스의constructor를 호출할 때 사용합니다.super()를 호출하기 전에는this를 사용할 수 없습니다. 부모 클래스의 속성들을 초기화하는 역할을 합니다.
class 문법은 이전의 생성자 함수 방식보다 훨씬 직관적이고 가독성이 좋습니다.
상속 연결은 계속 프로토타입을 사용하지만, class와 생성자 함수를 아무 차이 없이 바꿔 쓸 수 있는 것은 아닙니다. 클래스 본문은 엄격 모드이고 new 없이 클래스를 호출할 수 없으며, 위 클래스 메서드는 기본적으로 열거되지 않습니다. 여기서는 상속 모델이 같다는 범위에서 “문법적 설탕”이라고 부릅니다.
읽기와 쓰기를 구분하는 예시
보통의 쓰기 가능한 데이터 속성으로만 만든 예시입니다. 접근자·Proxy의 별도 동작은 여기서 다루지 않습니다.
const parentForLookup = { score: 10 };
const childForLookup = Object.create(parentForLookup);
console.log(childForLookup.score, Object.hasOwn(childForLookup, "score"));
childForLookup.score = 20;
console.log(childForLookup.score, parentForLookup.score);
delete childForLookup.score;
console.log(childForLookup.score);처음 출력은 10 false입니다. 자체 속성이 없으므로 부모에서 값을 읽습니다. 다음 출력은 20 10: 대입은 자식의 자체 속성을 만들고 부모 값은 유지됩니다. delete로 자식의 속성을 없애면 다시 부모에서 찾아 마지막 출력은 10입니다. 속성 탐색은 값을 복사해 저장하는 절차가 아닙니다.
독립 연습
위 코드의 childForLookup.score = 20;만 childForLookup.score = undefined;로 바꿉니다. 세 console.log의 출력과, 대입 직후 Object.hasOwn(childForLookup, "score")의 값을 예상하세요. undefined라는 값과 “속성이 없음”은 같은지 설명해 보세요.
속성이 undefined인 경우의 해설
출력은 10 false, undefined 10, 10입니다. 대입 직후 자체 속성은 존재하므로 Object.hasOwn은 true이고, 읽기는 그 속성의 값 undefined에서 멈춥니다. 부모의 10으로 자동 대체되지 않습니다. delete 뒤에야 자체 속성이 없어져 부모를 다시 검색합니다.
근거: MDN 프로토타입 탐색·속성 가리기, 클래스의 엄격 모드와 선언 규칙.
상속 메커니즘 요약
이번 장에서는 자바스크립트의 객체 지향 프로그래밍을 이해하는 데 가장 핵심적인 개념인 프로토타입(Prototype)과 이를 통한 상속(Inheritance)에 대해 깊이 있게 학습했습니다.
일반 객체는 [[Prototype]]을 통해 다른 객체 또는 null과 연결됩니다. 자체 속성에서 먼저 찾고, 없을 때만 그 연결을 따라갑니다.
이 연결을 따라 속성과 메서드를 찾는 프로토타입 체인, 생성자 함수의 prototype 프로퍼티, constructor 프로퍼티의 역할을 함께 살펴보았습니다.
마지막으로, ES6에서 도입된 class 키워드가 실제로는 프로토타입 기반 상속의 복잡한 구현을 감춰주는 문법적 설탕이라는 점을 명확히 인지했습니다.
class 문법을 사용하면 더욱 직관적이고 간결하게 객체 지향 코드를 작성할 수 있지만, 그 밑바탕에는 여전히 프로토타입 체인이 존재한다는 사실을 잊지 않는 것이 중요합니다.
프로토타입과 상속을 이해하면 객체가 속성과 메서드를 어디에서 찾는지 설명할 수 있습니다.
객체, 생성자 함수, 클래스를 직접 만들어 보며 프로토타입 체인이 어떻게 이어지는지 확인해 보세요.
다음 절에서는 같은 상태를 객체의 메서드로 관리할지, 순수 함수를 통해 새 값으로 변환할지 비교합니다. 콜백은 이 장의 마지막 절에서, Promise와 async/await는 다음 장에서 다룹니다.
프로토타입 문제를 만나면 먼저 속성이 인스턴스에 있는지, 프로토타입에 있는지, 또는 체인 끝까지 없는지를 분리해야 합니다.
앞의 프로토타입 속성 탐색 사슬 다이어그램은 상속 구조를 점검할 때의 확인 순서를 정리합니다.
프로토타입을 확인할 때는 인스턴스 자체 속성, 프로토타입 메서드, 체인 끝을 순서대로 따라가면 구조가 보입니다.