[TIL][JS] 프로토타입

ddoni·2020년 12월 21일
2
post-custom-banner

프로토타입 (Prototype)

1. 프로토타입 객체(Object.prototype)

클래스 기반 객체지향 프로그래밍 언어(Java, C++)은 클래스를 정의 후 객체(인스턴스)생성이 가능하지만 프로토타입 기반 객체지향 언어인 자바스크립트는 클래스 없이 객체 생성이 가능하다. (ECMAScript 6에서 클래스가 추가 되었다.)

자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있어 부모의 프로퍼티, 메소드를 상속받아 사용할 수 있다. 이러한 부모 객체를 프로토타입 객체(프로토타입)이라 한다.

student 객체에는 없는 프로퍼티, 메소드들이 prototype(proto)에 있어서 student 객체에도 사용가능하다.

자바스크립트의 모든 객체는 [[Prototype]] 이라는 인터널 슬롯(인터널 프로퍼티)를 가진다. [[Prototype]]의 값은 null 또는 객체(프로토타입 객체)이며 상속을 구현하는데 사용된다. 접근은 __proto__ 로 접근할 수 있다.

var student = {
  name: 'Lee',
  score: 90
}

console.log(student.__proto__ === Object.prototype); 
//true
//student 객체의 __proto__ property로 접근하면 부모 객체(prototype object)를 반환한다.

2. [[Prototype]] vs prototype 프로퍼티

  • [[Prototype]]

    함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯(인터널 프로퍼티) 이다.

    객체의 입장에서 자신의 부모 역할을 하는 프로토타입 객체를 가리킨다. (함수의 경우 Funtion.prototype)을 가리킨다.

  • prototype 프로퍼티

    함수 객체만 가지고 있는 프로퍼티이다.

    클래스를 통해 객체가 생성될때(인스턴스) 생성자 함수를 이용하게 된다. 함수를 통해 생성된 객체의 부모역할을 하는 객체를 가리킨다.

3. constructor 프로퍼티

프로토타입 객체(부모객체)는 constructor 프로퍼티를 갖는다. 이 프로퍼티는 객체의 입장에서 자신을 생성한 객체를 가리킨다.

class Person {
  constructor (name) {
    this.name = name;
  }
}

let foo = new Person('Lee');

foo;

Person.prototype.constructor === Person
//foo 객체의 부모객체를 생성한 것(Person)은 자기 자신이므로 Person이된다.
foo.constructor === Person
//foo 객체는 Person에 의해 생성되었다
Person.constructor === Function
//Person 객체를 생성한 것은 생성자 함수이므로 함수 객체이다.

foo 객체 입장에서 자신을 생성한 것은 Person()이므로 foo 객체의 프로토타입 객체는 Person.prototype이 된다.

4. Prototype chain

자바스크립트는 특정 객체의 프로퍼티나 메소드를 사용할려고 할때, 해당 객체에 없는 경우 [[Prototype]]이 가리키는 부모 객체에 해당 프로퍼티나 메소드가 있는지 검색하여 사용한다. 이를 프로토타입 체인이라 한다.

5. 객체 선언 방식에 따른 프로토타입 객체

✨ 객체 생성을 위한 리터럴방식, Object() 생성자 함수를 이용한 방식 모두 함수를 통해 생성하는 방법이다.

//리터럴 방식으로 생성된 객체(Object() 함수로 생성됨)
var person = {
  name: 'Lee',
  gender: 'male',
  sayHello: function(){
    console.log('Hi! my name is ' + this.name);
  }
};

person.__proto__ === Object.prototype
//person의 부모객체는 프로토타입 객체임
Object.prototype.constructor === Object
//프로토타입 객체의 생성자는 객체
Object.__proto__ === Function.prototype
//객체의 부모객체는 함수 프로토타입
Function.prototype.__proto__ === Object.prototype
//함수 프로토타입의 부모객체는 프로토타입 객체(함수도 객체의 일부니까!)

6. 프로토타입 객체의 확장

프로토타입 객체도 객체이므로 프로퍼티, 메소드를 추가/삭제 할 수 있다. 이렇게 추가/삭제 된 것은 프로토타입 체인에 반영된다.

7. 원시타입의 확장

원시타입의 데이터는 객체가 아니므로 프로퍼티, 메소드를 가질 순 없지만 원시타입으로 프로퍼티나 메소드를 호출 할 때 원시타입과 연관된 객체로 일시적으로 변환되서 프로토타입 객체를 공유하게 된다. (프로퍼티, 메소드 추가는 불가능)

String.prototype, Number.prototype, Array.prototype

8. 프로토타입 객체의 변경

객체를 생성할 때 프로토타입은 결정된다. 결정된 프로토타입 객체는 다른 임의의 객체로 변경할 수 있다. (부모 객체를 동적으로 변경할 수 있음)

post-custom-banner

1개의 댓글

comment-user-thumbnail
2021년 3월 25일

ㅂ...배우고 갑니다..

답글 달기