728x90

prototype은 ES6 이전 class 키워드가 존재하지 않았을 때까지 javascript코드를 객체지향적으로 구현하기위해 사용하였다.

prototype으로 객체를 정의할 수 있음은 물론 상속을 구현할 수도 있었기 때문에 class의 대체가 되었지만,

많은 객체지향언어에서 class의 개념이 완벽히 고정되어 많은 개발자들 사이에서도 class가 사용하기 편한 세상이 되었기 때문에 ES6부터 class를 지원하게 되었다.

ES6이후에도 class를 사용하면 기본적으로 해당 class안에 정의된 함수는 prototype에 정의된다. javascript의 class 지원은 개발자의 편의성을 위한 것이지 여전히 javascript는 prtotype based language인 것이다.

객체지향 언어의 개념(class의 개념)을 알고 있다면 prototype에 대한 이해는 쉬울 것이다.

차이점이라곤 객체를 함수를 통해 정의한다는 것 뿐이다.

이제부터 prototype을 프로토타입 자신을 통해 만들어질 객체의 원형이라고 생각하자.

class vs prototype

class

다음과 같이 선언된 class가 있다.

let PersonC = class {
  constructor(nm,id){
    this.name = nm;
    this.id = id;
  }
  getDetails(){ // exist on prototype of PersonC
    return `${this.name} :: ${this.id}`
  }
}

let bob = new PersonC('Bob',123); 
console.log(bob.getDetails(),bob.name); // Bob :: 123 Bob

let EmployeeC = class extends PersonC{ //EmployeeC prototype links to PersonC prototype
  constructor(nm,id,salary){
    super(nm,id);
    this.salary = salary;
  }
  employeeInfo(){ // exist on prototype of EmployeeC
    return `${this.name} :: ${this.id} :: ${this.salary}`;
  }
}

let noomi = new EmployeeC('Noomi',456,800);
console.log(noomi.employeeInfo()); //  Noomi :: 456 :: 800

먼저 class로 구현된 PersonC의 구조를 보자. 앞에서 말했듯이 javascript는 prototype based language이기 때문에 prototype으로 재정의되어 저장되어있다.

class 안에 getDetails는 prototype에 저장되어있다. 이렇게 class 안에 선언된 메서드는 prototype에 저장되게 된다.

PersonC 를 상속받고 있는 EmployeeC의 구조는 복잡하다. 하지만 한가지만 알면된다. PersonC의 getDetails 가 선언된 장소가 prototype안에 constructor안에 prototype 안에 있다. 이 의미는 바로 EmployeeC 클래스 안에 getDetails 메서드가 override 되어있지 않으면 getDetails 메서드의 정의를 찾을 때까지 prototype을 깊게 탐색한다는 것이다.

만약 EmployeeC에 getDetails 메서드가 override되어 있었다면 해당 getDetails 메서드를 호출할 것이다.

new means call this function as a constructor changing context

prtotype

위의 class로 구현된 부분을 똑같이 prototype으로 구현해보겠다.

let PersonP = function(nm,id){
  this.name = nm;
  this.id = id;
}

PersonP.prototype.getDetails = function() {
  return `${this.name} :: ${this.id}`;
}

let fred = new PersonP('Fred',321);
console.log(fred.getDetails(),fred.name); // Fred :: 321 Fred

let EmployeeP = function(nm,id,salary){
  PersonP.call(this,nm,id);
  this.salary = salary;
}

Object.setPrototypeOf(EmployeeP, PersonP.prototype); //extends,EmployeeP prototype links to PersonP prototype

EmployeeP.prototype.employeeInfo = function(){
  return `${this.name} :: ${this.id} :: ${this.salary}`
}

let mary = new EmployeeP('mary',345,100);
console.log(mary.employeeInfo()); // mary :: 345 :: 100

prototype에는 extends 키워드가 존재하지 않기때문에 상속을 구현하기 위해서는 setPrototypeOf 키워드를 사용한다.

class에서 사용하던 super도 없기때문에 super대신 상속받은 상위 객체의 cosntructor를 직접 호출하여 prototype변수를 초기화한다.

prototype 객체안에 객체를 선언하기 위해서는 class선언 결과에서 보았듯이 객체의 prototype에 함수를 직접 정의하면된다.


prototype object & prototype link

prototype은 prototype object, prototype link 이 두가지의 개념으로 구성되어있다.

prototype object

함수형으로 객체를 정의할때 Object 타입의 prototype을 부여받는다. 다음 예제를 통해 prototype object가 어떤 구조를 가지고 있는지 보도록하자.

function Person(){}

Person 객체 정의시

Person 객체Person 함수의 프로토타입 객체가 생성되며

각 객체는 서로 연결 되어 있다.

위의 구조가 어떤의미를 가지고 있는지 알아보도록 하자.

  1. new를 통해 해당 함수에 constructor(생성자) 자격을 부여한다
  2. 해당 함수의 prototye object 생성 및 연결
    • 함수의 prototype은 prototype object를 연결하고 prototype object의 constructor는 함수를 가르키기 때문에 prototype object또한 하나의 property처럼 변수 또는 함수를 추가하며 자유롭게 이용 가능하다.
    • __proto__로 prototype link이며 상속의 개념을 가지도록 하였다.

prototype link

함수 생성시 prototype object에서 같이 정의 되었던 __proto__이다.

prototype내에 선언된 변수 또는 함수를 객체가 직접 prototype object에 들어가지 않아도 참조할 수 있게 해주는 역할을 한다.

__proto__는 객체가 생성될때 조상이었던 함수 Prototype Object를 가르킨다. 위의 예제에서 __proto__는 Object Prototype Object를 가르킨다.

javascript는 기본적으로 본인이 가지고 있지않은 변수 또는 메서드를 찾을때까지 __proto__를 타면서 하위 prototype부터 최상위 prototype까지 훑어 올라간다.

Object는 항상 prototype object의 최상위 객체이다.

이것이 상속의 개념이 토대가 되며 상속은 보통 \_\_proto\_\_를 직접 선언해서 정의한지않고 setPrototypeOf 함수를 이용하여 상속을 정의한다.

'Javascript' 카테고리의 다른 글

await event  (1) 2021.07.30
Image Lazy Loading  (0) 2021.07.24
var vs let (const)  (0) 2021.01.13
비동기 처리 - async/await  (0) 2020.12.27
비동기 처리 - Promise  (0) 2020.12.20

+ Recent posts