[ TIL 02 ] Prototype

박재영·2020년 6월 21일
1

Prototype

1. What is Prototype? Why use it?

(1) Prototype이란

  • 생성자 함수를 호출시 참조가 되는 원형객체
  • 같은 생성자 함수로 생성된 instance들은 Prototype 객체에 들어있는 속성들을 공유함
  • 모든 객체는 원형객체에 대한 참조값을 내부 속성 __proto__에 가지고 있음

(2) Prototype을 사용하는 이유

  • 생성자 함수 안에서 instance에 메서드를 지정하면 instance를 생성할 때마다 같은 기능을 하는 메서드들을 매번 새로운 메모리에 할당을 하게 됨
  • Prototype 객체의 속성에 단 한 번 메서드를 지정하면 메모리를 매번 새로 할당하지 않아도 Prototype 객체의 속성을 참조하여 메서드를 사용할 수 있음

2. __proto__ , Prototype, constructor


function CleaningRoster(classRoom){
  this.classRoom = classRoom;
}

CleaningRoster.prototype.cleaning = function(){
  console.log(`${this.classRoom}반에서 청소를 실시합니다.`);
}

function WindowCleaningRoster(classRoom){
  CleaningRoster.call(this,classRoom);
  this.WindexLiter = 10;
  this.extentTowelDirty = 0;
}

WindowCleaningRoster.prototype = Object.create(CleaningRoster.prototype);
WindowCleaningRoster.prototype.constructor = WindowCleaningRoster;
WindowCleaningRoster.prototype.printRole = function(){
  console.log('창문 닦기 담당입니다.');
}

const minho = new WindowCleaningRoster('2-2');
minho.cleaning(); // 2-2반에서 청소를 실시합니다.
minho.printRole(); // 창문 닦기 담당입니다.
  • 위 코드는 WindowCleaningRoster가 CleaningRoster를 상속받는 과정을 구현한 것이다.

  • function은 생성할 때 inner slot(property)으로 prototype속성(객체)을 가진다.

  • prototype 객체 안에는 constructor 속성이 존재하며 해당 prototype 속성을 가진 function을 가리킨다.
    CleaningRoster.prototype.constructor === CleaningRoaster
    WindowCleaningRoster.prototype.constructor === WindowCleaningRoster

  • function의 prototype 속성에 접근하여 인스턴스들이 공유해서 사용할 프로퍼티와 메서드를 지정할 수 있다.

  • function이 new 연산자로 사용될 때 생성된 인스턴스들의 속성 __proto__의 값에 function의 속성 prototype 객체를 할당한다.

    minho. __proto__ === CleaningRoster.prototype

  • WindowCleaningRoster의 prototype은 Object.create를 사용하여 CleaningRoster의 prototype 객체를 상속받고 있다. 이때 prototype 객체가 참조하던 값이 바뀌었으므로 prototype의 속성 constructor 또한 CleaningRoster로 바뀐다. 따라서 constructor에 다시 WindowCleaningRoster함수를 참조하도록 지정해줘야 한다.

  • WindowCleaningRoster 생성자 함수를 통해 생성된 인스턴스 minho는 cleaning메서드를 호출해도 에러가 발생하지 않는다. 그 까닭은 객체의 프로퍼티, 메서드에 해당 프로퍼티나 메서드가 없다면 객체의 prototype(__proto__)을 탐색한다. 객체의 prototype에도 발견하지 못하면 계속해서 객체의 prototype의 prototype을 탐색한다. 이 과정을 prototype chain 이라 부른다. minho의 경우 minho 자신의 메서드에 cleaning이 없으므로 minho의 prototype인 CleaningRoster을 탐색한다. CleaningRoster에 cleaning 메서드가 존재하므로 탐색을 중지하고 CleaningRoster의 cleaning 메서드를 호출한다.

사실 생성자 함수를 다시 원래 자신을 가르키도록 지정 안 해도 작동 상에선 아무 문제 없지만 지정해주는 까닭은 정확한 설계, 구조로 짜야 그 코드가 좋은 코드이기 때문. 다른 사람이 해당 코드를 봐도 혼란을 느끼지 않도록 함. 생성자 함수는 이름을 지을 때 대문자로 시작하도록 약속한 것도 실행 상엔 문제가 없지만 코드 가독성을 위해 다같이 그 규칙을 따르는 것과 비슷한 맥락



예제 참고사이트 : youtube 얄팍한코딩사전, 객체지향프로그래밍

2개의 댓글

comment-user-thumbnail
2020년 6월 21일

object.create()로 prototype에 할당할 때 constructor를 따로 지정안해줘도 작동하는데는 문제가 없군요. 거기까진 생각을 안해봤는데 그렇겠네요. 좀 찝찝하긴 하겠지만... __proto__.constructor해서 확인하는 거 아니면 딱히 차이점은 없겠다 싶네요.

그리고 전 얼마전까지만해도 ㅋㅋㅋㅋ 생성자 함수이름 첫 글자 대문자로 하는게 암묵적인 규칙이 아니고, 그렇게 안하면 그냥 일반함수가 되는 줄 알았어요.... ㅎㅎ ;;

1개의 답글