jgjgill

프로토타입이란?

No Filled

자바스크립트에서 객체가 다른 객체의 속성과 메서드를 참조할 수 있게 해주는 링크 메커니즘으로, 클래스 기반 언어의 상속을 구현하는 자바스크립트만의 방식

기본 개념

  • 프로토타입은 자바스크립트 객체가 가지고 있는 숨겨진 속성으로 다른 객체를 가리키는 내부 링크
  • 모든 객체는 [[Prototype]]이라는 내부 슬롯 소유
  • 이를 통해 다른 객체의 속성과 메서드를 상속 가능

등장 배경

  • 자바스크립트는 클래스 기반이 아닌 프로토타입 기반 언어로 설계
  • 다음과 같은 문제를 해결하기 위해 프로토타입을 도입
    • 메모리 효율성: 모든 객체마다 메서드를 복사하지 않고 공유
    • 동적 상속: 런타임에 상속 관계를 변경 가능
    • 유연한 객체 확장: 기존 객체에 기능을 동적으로 추가

동작 원리

프로토타입 흐름

프로토타입 체인 탐색 과정

  • 객체의 속성에 접근 시도
  • 해당 객체에 속성이 있으면 반환
  • 없으면 [[Prototype]] 링크를 따라 부모 객체에서 탐색
  • 찾을 때까지 또는 null을 만날 때까지 체인을 따라 계속 탐색

관련 개념과 비교

프로토타입 비교

클래스 vs 프로토타입

  • 클래스: 설계도를 먼저 만들고 복사 (Java, C++)
  • 프로토타입: 객체를 직접 연결하여 공유 (JavaScript)

__proto__ vs prototype

  • __proto__: 모든 객체가 가진 실제 프로토타입 링크
  • prototype: 함수 객체만 가진 속성, 생성자로 사용될 때 인스턴스의 proto가 가리킬 객체

예시 코드

// 생성자 함수
function Person(name, age) {
  this.name = name
  this.age = age
}

// prototype에 메서드 추가
Person.prototype.greet = function () {
  return `안녕하세요, 저는 ${this.name}입니다.`
}

Person.prototype.species = 'Human'

// 인스턴스 생성
const john = new Person('John', 30)
const jane = new Person('Jane', 25)

console.log(john.greet()) // "안녕하세요, 저는 John입니다."
console.log(jane.greet()) // "안녕하세요, 저는 Jane입니다."

// 프로토타입 체인 확인
console.log(john.hasOwnProperty('name')) // true (자신의 속성)
console.log(john.hasOwnProperty('greet')) // false (프로토타입 속성)
console.log(john.species) // "Human"

// 프로토타입 관계 확인
console.log(john.__proto__ === Person.prototype) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__) // null

// 안녕하세요, 저는 John입니다.
// 안녕하세요, 저는 Jane입니다.
// true
// false
// Human
// true
// true
// null

프로토타입 체인 비교

// Object.create를 사용한 프로토타입 상속
const animal = {
  type: 'Animal',
  speak() {
    return `${this.name} makes a sound`
  },
}

const dog = Object.create(animal)
dog.name = 'Buddy'
dog.bark = function () {
  return 'Woof!'
}

console.log(dog.speak()) // "Buddy makes a sound"
console.log(dog.bark()) // "Woof!"
console.log(dog.type) // "Animal" (프로토타입에서 상속)

// 클래스 문법 (내부적으로는 프로토타입 사용)
class Animal {
  constructor(name) {
    this.name = name
  }

  speak() {
    return `${this.name} makes a sound`
  }
}

class Dog extends Animal {
  bark() {
    return 'Woof!'
  }
}

const puppy = new Dog('Max')
console.log(puppy.speak()) // "Max makes a sound"
console.log(puppy.bark()) // "Woof!"

// 두 방식 모두 내부적으로는 프로토타입 체인 사용
console.log(puppy.__proto__ === Dog.prototype) // true

헷갈리기 쉬운 부분

__proto__ vs prototype의 정확한 차이

function Car() {}

const myCar = new Car()

// prototype: 생성자 함수의 속성
console.log(Car.prototype) // { constructor: Car }
console.log(myCar.prototype) // undefined (인스턴스는 prototype 없음)

// __proto__: 실제 프로토타입 링크
console.log(myCar.__proto__) // Car.prototype과 같은 객체
console.log(myCar.__proto__ === Car.prototype) // true
  • prototype: 함수 객체만 가지는 속성, 생성자로 사용될 때 인스턴스가 참조할 프로토타입 객체
  • __proto__: 모든 객체가 가지는 실제 프로토타입 링크, Object.getPrototypeOf()로 접근 권장

오해: 프로토타입은 복사다

// ❌ 잘못된 이해: 프로토타입은 복사되지 않습니다
Person.prototype.species = 'Human'
const person1 = new Person('Alice', 20)

// 프로토타입 수정 시 모든 인스턴스에 반영
Person.prototype.species = 'Homo Sapiens'
console.log(person1.species) // "Homo Sapiens" (복사가 아니라 참조!)

프로토타입 체인과 속성 검색

function Parent() {}
Parent.prototype.value = 10

function Child() {}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.value = 20 // 오버라이딩

const child = new Child()
child.value = 30 // 인스턴스 속성

console.log(child.value) // 30 (인스턴스 속성)
delete child.value
console.log(child.value) // 20 (Child.prototype.value)
delete Child.prototype.value
console.log(child.value) // 10 (Parent.prototype.value)

프로토타입 체인의 끝은?

  • Object.prototype.__proto__null
  • 모든 객체의 프로토타입 체인은 결국 Object.prototype에서 끝남

개념 정리

프로토타입이 무엇인가요?

프로토타입은 자바스크립트 객체가 다른 객체로부터 속성과 메서드를 상속받을 수 있게 해주는 메커니즘입니다.

자바스크립트는 클래스 기반이 아닌 프로토타입 기반 언어입니다. 모든 객체는 내부적으로 [[Prototype]]이라는 숨겨진 링크를 가지고 있으며, 이를 통해 다른 객체를 참조합니다. 이러한 연결 고리를 '프로토타입 체인'이라고 합니다.

작동 방식은 객체의 속성에 접근할 때 해당 속성이 객체 자체에 없으면, 자바스크립트 엔진은 프로토타입 체인을 따라 상위 객체에서 해당 속성을 찾습니다. 이 과정은 속성을 찾거나 체인의 끝인 null을 만날 때까지 계속됩니다.

예를 들어 생성자 함수로 객체를 만들 때 new 키워드를 사용하면, 생성된 인스턴스의 [[Prototype]]은 생성자 함수의 prototype 속성을 가리킵니다. 이를 통해 모든 인스턴스가 메서드를 공유할 수 있어 메모리를 효율적으로 사용할 수 있습니다.

프로토타입을 이해하는 것은 자바스크립트의 상속 메커니즘을 이해하는 핵심이며, ES6의 클래스 문법도 내부적으로는 프로토타입을 사용합니다.

핵심 문장

  • 프로토타입은 자바스크립트 객체 간의 상속을 구현하는 메커니즘
  • 모든 객체는 다른 객체를 참조하는 내부 링크 가지며, 속성을 찾을 때 이 체인을 따라 상위 객체를 탐색
  • 생성자 함수의 prototype 속성에 메서드를 정의하면 모든 인스턴스가 이를 공유하여 메모리를 효율적으로 사용 가능
@2023 powered by jgjgill