본문 바로가기

자바스크립트

프로토타입(prototype)

프로토타입

  • 프로토타입은 객체가 가진 기본 속성과 메서드를 정의하는 객체로써 객체간의 상속을 구현하는데 사용된다.
  • 모든 자바스크립트 객체는 다른 객체로부터 속성과 메서드를 상속받을 수 있는 숨겨진 링크(프로토타입 체인)를 가지고 있다.

 

프로토타입의 구조와 개념

어떤 생성자 함수(constructor)를 new 연산자와 함께 호출하면 constructor에서 정의된 내용을 바탕으로 새로운 instance가 생성된다.
이때 instance에는 __proto__라는 constructor의 prototype 프로퍼티를 참조하는 프로퍼티가 자동으로 부여된다.
// Constructor : 함수 객체이며, prototype 프로퍼티를 가짐
function Person(name) {
    this.name = name;
}

// prototype에 메서드 추가
// prototype : 모든 인스턴스가 공유하는 메서드와 속성을 저장
Person.prototype.sayHello = function() {
    console.log(`Hello, I'm ${this.name}`);
};

// Person 생성자로 만들어진 인스턴스
// __proto__로 Person.prototype 참조 가능
const john = new Person('John');

 

1. Constructor

console.log(Person.prototype.constructor === Person); // true
console.log(john.constructor === Person); // true
  • 객체를 생성하는 생성자 함수
  • constructor.prototype 에는 constructor 라는 프로퍼티가 있는데, 이는 다시 생성자 함수 자신을 가리킨다.
  • constructor 는 인스턴스가 자신의 생성자 함수가 무엇인지 식별할 수 있는 속성이다.
  • prototype을 확인하기 위해 constructor를 확인해볼 수 있지만, 변경 가능하므로 항상 안전한 것은 아님

 

2. prototype

  • 생성자 함수의 프로토타입 객체
  • 모든 인스턴스가 공유하는 메서드와 속성을 저장
  • 생성자 함수만 가진 속성
  • 해당 함수로 생성될 객체들이 상속받을 프로토타입 객체를 가리킴

 

3. instance

  • 생성자 함수(constructor)로 만들어진 객체
  • __proto__ 로 생성자 함수의 prototype 을 참조할 수 있다.
console.log(john instanceof Person); // true
console.log(john instanceof Object); // true (모든 객체는 Object의 인스턴스)
  • instanceof 연산자로 객체가 특정 생성자 함수의 프로토타입 체인에 속하는지 확인할 수 있다.

 

4. __proto__

// 프로토타입 접근 방법들
console.log(john.__proto__ === Person.prototype); // true
console.log(Object.getPrototypeOf(john) === Person.prototype); // true

// 권장되는 프로토타입 접근 방법
const proto = Object.getPrototypeOf(john); // 객체의 프로토타입 반환
const newObj = Object.create(Person.prototype); // 새로운 객체 생성, 특정 프로토타입으로 설정
  • 모든 객체가 가진 속성
  • 해당 객체의 부모 프로토타입 객체를 참조(객체의 프로토타입 링크)
  • __proto__는 생략가능한 속성이라 인스턴스는 constructor.prototype의 메서드를 마치 자신의 메서드인 것처럼 호출할 수 있다.
  • prototype 프로퍼티 내부의 메서드만 접근할 수 있으며 외부 메서드들은 생성자 함수에서 직접 접근해야한다.
  • ES6부터 비표준 간주 및 브라우저 호환성과 성능을 위해 Object.getPrototypeOf() / Object.create() 사용 권장

 

prototype과 __proto__ 의 주요 차이점

  • prototype은 생성자 함수에만 존재
  • __proto__는 모든 객체에 존재
  • 인스턴스는 __proto__를 통해 생성자의 prototype에 접근할 수 있다.

 

프로토타입 체인

  • 객체들이 서로 연결된 구조
  • 각 객체는 다른 객체를 가리키는 내부 링크(프로토타입)를 가지고 있으며, 이 링크들이 연결되어 체인을 형성한다.

 

프로토타입 체인의 작동 방식

  1. 객체에서 프로퍼티나 메서드를 찾을 때, JS 엔진은 먼저 해당 객체를 검색한다.
  2. 해당 객체에 찾는 프로퍼티나 메서드가 없으면, 객체의 프로토타입으로 이동해서 다시 검색한다.
  3. 이 과정을 프로토타입 체인의 끝(보통 Object.prototype)에 도달할 때까지 반복한다.
  4. 끝까지 찾지 못할경우 undefined를 반환한다.

→ 이런식으로 찾아가는 과정을 프로토타입 체이닝이라고 하며, 이 프로토타입 체이닝을 통해 각 프로토타입 메서드를 자신의 것처럼 호출할 수 있다.

 

 

메서드 오버라이드(Method Override)

  • 하위 객체에서 상위 객체의 메서드를 동일한 이름으로 재정의하는 것
  • 과도한 오버라이드는 코드 복잡성을 증가시키므로 성능과 가독성을 고려해야한다.
const parent = {
  greet() {
    console.log("안녕하세요!");
  }
};

const child = Object.create(parent);
child.greet = function() {
  console.log("안녕!");
};

child.greet(); // "안녕!"

 

 

객체 메서드의 예외사항

모든 생성자 함수의 prototype 은 반드시 객체이므로 Object.prototype 이 언제나 프로토타입 체인의 최상단에 존재한다.
그에따라 객체에서만 사용할 메서드는 다른 데이터 타입처럼 프로토타입 객체안에 정의 할 수가 없다.
→ 객체에서만 사용할 메서드를 Object.prototype 내부에 정의하면 다른 데이터 타입도 해당 메서드를 사용할 수 있기 때문!
  • Object.prototype 의 메서드 - 모든 객체가 상속받아 사용 가능
Object.prototype.toString();
Object.prototype.hasOwnProperty();
Object.prototype.valueOf();
Object.prototype.isPrototypeOf();
⋮
  • 객체 전용 메서드 - 다른 데이터 타입과 달리 Object 생성자 함수에 static 하게 담겨있다.
  • 정적 메서드는 객체 인스턴스가 아닌 Object 생성자 함수를 통해 직접 호출해야 한다.
  • 객체에서만 사용할 메서드는 Object.prototype이 아닌 정적 메서드로 정의해야 한다.
Object.keys();
Object.values();
Object.entries();
Object.assign(); 
Object.create();
⋮

 

 

다중 프로토타입 체인

  • 계층적 상속 구조를 구현할 때 사용하고 여러 단계의 상속 메서드와 프로퍼티에 접근 가능하다.
  • 과도하게 깊은 상속 구조는 성능 저하 가능성이 있으므로 신중하게 사용 or ES6의 class 문법을 사용하는 것을 권장한다.

 

 

'자바스크립트' 카테고리의 다른 글

클로저  (0) 2024.12.15
콜백함수  (0) 2024.12.14
this  (0) 2024.12.13
실행컨텍스트(Execution Context)  (0) 2024.12.03
얕은복사와 깊은복사, structuredClone()  (0) 2024.12.02