Prototype과 Class

조양권·2021년 5월 18일
0

JS

목록 보기
9/17

JS는 기본적으로 객체지향으로 만들어진 언어가 아니다. 따라서 ec6이전에는 class조차 없었으며 class가 없으니 상속기능도 없었다. 그래서 보통 프로토타입(prototype)을 기반으로 상속을 흉내내도록 구현했었다.

프로토타입(prototype)

function ice_cream(){
  this.temp = 'cold'
  this.sweet = true
}
let world_con = new ice_cream();
let nugabar = new ice_cream();

위의 방식대로 사용하게 된다면 메모리에는 temp와 sweet이 총 두개씩 4개가 할당이 된다. 아이스크림의 종류가 늘어날 수록 할당되는 메모리의 양도 기하급수적으로 늘어난다. 이를 프로토타입으로 해결할 수 있다.

function ice_cream(){}
ice_cream.prototype.temp = 'cold'
ice_cream.prototype.sweet = true
let world_con = new ice_cream();
let nugabar = new ice_cream();

위를 보면 ice_cream.prototype이라는 빈 객체가 어디엔가 존재하며 ice_cream 함수로부터 생성된 객체들은 이 어딘가 존재하는 prototype object를 가져다 사용(상속)할수 있다.

프로토타입은 프로로타입 링크(prototype link)와 프로토타입 오브젝트(prototype object)가 있으며, 이둘을 통틀어 프로토타입이라고 부른다.

프로토타입 오브젝트(prototype object)

객체는 언제나함수로 생성된다. 아래의 객체를 만드는 과정은 모두 동일하다.

function make_obj(){...}
let obj = new make_obj()
///
let obj = {}
///
let obj = new Object()

Object()또한 자바스크립트에서 기본적으로 제공하는 객체를 만드는 함수이다. 함수가 정의될때에는 두가지 일이 발생한다.

  1. 해당 함수에 생성자(constructor)부여
    생성자가 부여된다면 new를 통해 객체를 만들어 낼 수 있게된다.

  2. 해당함수의 prototype object 생성 및 연결
    함수가 정의될때 함수 뿐 아니라 prototype object또한 같이 생성된다. 그리고 생성된 함수는 prototype이라는 속성을 통해 prototype object에 접근할 수 있다. prototype object는 기본적인 속성으로 constructor와 __proto__를 가지고 있다.

constructor는 prototype object와 같이 생성되었던 함수를 가리킨다.

__proto__는 prototype link이다.

function ice_cream(){}
ice_cream.prototype.temp = 'cold'
ice_cream.prototype.sweet = true
let world_con = new ice_cream();
let nugabar = new ice_cream();
wolrd_con.temp // 'cold'

위의 예제에서 world_con에는 temp라는 속성이 없는데 어떻게 참조가 가능할까. 그것은 __proto__가 존재하기 때문이다. prototype속성은 함수만 가지고 있었던 것에 반해 __proto__는 모든 객체가 가지고 있는 속성이다.

__proto__는 객체가 생성되었을 때에 조상이었던 함수의 prototype object를 가리킨다. wolrd_con은 ice_cream으로부터 생성되었으니 world_con.__proto__는 ice_cream.prototype과 같다.

이렇게 __proto__속성을 통해 상위 프로토타입과 연결되있는 것을 prototype link라고 한다. 이러한 프로토타입의 체인구조 때문에 모든 객체는 Object의 자식이며, Object.prototype을 사용할 수 있다.

프로토타입 상속(prototype inheritance)

function ice_cream(name){
  this.is_cold = true
  this.sweet = true
}
ice_cream.prototype.melt_down = function(){
  this.is_cold = false
  console.log('no!!')
}

아이스크림 생성자를 만들어 보았다. 차가운지(is_cold),달콤한지(sweet) 그리고 녹았을때의 메소드만을 정해놓았다. 그리고 돼지바의 생성자 또한 만들어 보겠다.

function pig_bar(name){
  this.crispy = true
}

바삭한지(cirspy)의 여부만을 추가하고 나머지 속성 및 메소드는 ice_cream의 것을 가져올것이다.

프로토타입의 상속은 다음과 같은 단계로 진행된다.

  1. 자식의 생성자의 프로토타입 객체를 부모의 프로토타입객체를 프로토 타입으로 하는 객체로 설정한다
function pig_bar(name){
  this.crispy = true
}
pig_bar.prototype = Object.create(ice_cream.prototype)
  1. 생성된 자식 생성자의 프로토 타입 객체의 constructor를 자식 생성자로 설정한다.
function pig_bar(name){
  this.crispy = true
}
pig_bar.prototype = Object.create(ice_cream.prototype)
pig_bar.prototype.constructor = pig_bar
  1. 자식 생성자가 실행될 때 부모 생성자도 실행되게 하여 해당 속성을 자식 생성자의 this객체에 할당한다.
function pig_bar(name){
  ice_cream.call(this,name)
  this.crispy = true
}
pig_bar.prototype = Object.create(ice_cream.prototype)
pig_bar.prototype.constructor = pig_bar

클래스(class)

자바스크립트 ES2015부터는 이런 프로토 타입의 생성과정을 더욱 쉽게 하기 위해 클래스가 도입되었다. 아래의 예제는 위의 돼지바만들기와 동일하다.

class ice_cream{
  constructor(name){
    this.is_cold = true
    this.sweet = true
  }
  melt_down(){
    this.is_cold = false
    console.log('no!!')
  }
}
class pig_bar extends ice_cream {
  constructor(name){
    super(name)
    this.crispy = true
  }
}

ice_cream클래스의 constructor 객체는 객체의 속성을 정의하는 곳이다. 생성자 함수와 동일하게 this 객체에 속성을 할당하는 방식이다.

메소드는 constructor객체 아래에 동일하게 함수식으로 작성하면 된다.

pig_bar가 ice_cream의 하위객체라면 extends와 super키워드를 사용한다.

pig_bar만이 가지고 있는 속성이 있다면 constructor객체 안에 정의하면 된다.

super는 상위 클래스(ice_cream)를 호출할때 사용된다.

profile
할 수 있는 것이 늘어나는 즐거움

0개의 댓글