p r o g r a m m i n g

OOP / prototype 이해를 위해

hee.hee 2022. 5. 25. 15:30

 

프로토타입이란?
자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.
중복을 제거하는 방법은, 기존의 코드를 적극적으로 재사용하는 것이다.
생성자 함수가 생성할 모든 인스컨스가 공통적으로 사용할 프로퍼티나 메서드를 프로토타입에 미리 구현해두어 생성자 함수가 생성할 인스턴스는 별도의 구현 없이 상위 객체인 프로토타입의 자산을 공유하여 사용할 수 있다.

프로토타입 객체란, 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용된다. 프로토타입(객체)는 어떤 객체의 상위(부모)객체의 역할을 하는 객체로서 다른 객체에 공유프로퍼티(메서드 포함)를 제공한다. 프로토타입을 상속받은 자식 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 사용할수 있다.

__proto__ 접근자 프로퍼티
모든 객체는 __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[prototype]] 내부 슬롯에 간접적으로 접근할 수 있다. 부모 클래스의 프로토타입, 혹은 '부모의 부모 클래스'의 프로토타입을 탐색할 수 있습니다.

함수객체의 prototype 프로퍼티
함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킴. 생성자함수가 자신이 생성할 객체(인스턴스)의 프로토타입을 할당하기 위해 사용한다.

 

 

 

constructor 생성자 함수

  • 인스턴스 객체를 생성하고 초기화하는 메서드
  • 클래스 내에서 생성자 함수는 한번만 쓸 수 있음
  • 생성자 함수를 작성하지 않으면 기본 생성자(default constructor) 제공됨
  • 부모 클래스가 있을 때(derived) 기본 생성자는 부모 생성자
  • 기본 클래스인 경우 기본 생성자는 비어 있음

(헷갈리니까 그냥 이렇게 알고 있기)

 

 

 

 

super 키워드

부모 클래스의 함수를 호출할 때 사용

생성자 함수 내에서 super 키워드는 한번만 사용

생성자 함수 내에서 this 키워드가 나오기 전에 사용 (Reference error)

생성자 함수 내에서 super을 호출하면 부모 클래스의 생성자 함수를 호출

 

 

 

최상위 클래스 (프로토타입 체인 과정)

let div = document.createElement('div');

div.__proto__   //HTMLDivElement
div.__proto__.__proto__   //HTMLElement
div.__proto__.__proto__.__proto__    //Element
div.__proto__.__proto__.__proto__.__proto__    //Node
div.__proto__.__proto__.__proto__.__proto__.__proto__    //EventTarget
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__     //Object
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__    //null

JavaScript는 프로토타입 기반 언어이며, DOM도 프로토타입으로 상속을 구현한다.
보통 클래스의 인스턴스는 new 키워드로 생성하지만, DOM에서는 new 키워드가 아닌 createElement를 사용.
JS의 거의 모든 객체는 Object의 인스턴스이다. 즉, Object는 거의 모든 객체의 조상이다.
때문에 모든 객체들의 조상인 Object의 porotype은 null이 나온다.

 

 

 

 

 

프로토타입 연습문제

class Human {
    constructor(name, age){
        this.name = name; 
        this.age = age;
    }
    sleep(){ return `${this.name}이(가) 잠을 잡니다.`}
}

class Student extends Human{
    constructor(name, age, grade){
        super(name, age);
        this.grade = grade;
    }
    study(num){
        this.grade = this.grade + num;
        return `${this.name}의 성적이 ${num}만큼 올라 ${this.grade}이 되었습니다.`
    }
}

let mincoding = new Student('민학생', 19, 70);
  1. mincoding.__proto__는 Student.prototype과 같다.
  2. mincoding.__proto__.__proto__는 Human.prototype과 같다.
  3. mincoding.__proto__.__proto__.__proto__는 Object.prototype과 같다.
  4. mincoding.study(10)은 사용할 수 있다.
  5. mincoding.sleep은 사용할 수 없다.

Student의 인스턴스인 mincoding은 Human의 프로토타입에 있는 sleep을 사용할 수 있습니다. 왜냐하면 Student 클래스는 Human 클래스를 상속받았기 때문입니다. (Human의 메서드는 Human의 프로토타입에 있다)

 

 

 

 

 

 

 

prototype과 __proto__의 사용

https://www.youtube.com/watch?v=wT1Bl5uV27Y 

여기서 class, class 객체란, 함수와 같은 의미.(class와 함수가 헷갈렸는데, 이제 생성자 함수까지 헷갈린다)

class가 만들어질 때, 'class' 객체와 ' 객체의 'prototype 객체'가 생성됨.

'class'(분홍색) 내부에는 prototype 프로퍼티가 생성되고, 'prototype 객체'(초록색)와 연결됨

class이름.prototype -> 'prototype객체' 로 연결.

'prototype객체' 안에도 class와의 연결을 위해 constructor라는 프로퍼티를 만들고, 그 프로퍼티를 class 객체에 연결시킴

이렇게 하면 class객체와 prototype객체가 상호참조의 상태가 된다.

 

이 class를 이용해 인스턴스를 생성하면, class의 생성자 함수를 통해 인스턴스의 프로퍼티들이 만들어짐(노란색, kim)

이 때 인스턴스의 프로퍼티 중,  __proto__가 생기는데, class의 prototype 객체를 가리킴(초록색)

그럼, person.prototype === kim.__proto__ 가 true. 둘 다 같은, person's prototype을 가리킴.

 

인스턴스에서 프로퍼티를 조회할 때, 해당 내용이 없으면 __proto__를 통해, 걔가 가리키고 있는 'class의 prototype'으로 간다.

즉, 자식에 없으면 부모의 prototype을 조회.

부모의 prototype 역시 객체이기 때문에, 걔한테도 참조할 prototype이 있다. 그 위로 올라가 조회함.

 

이러한 원리로, 어떤 객체가 가지고 있지 않은 정보를 사용하려고 할 때, __proto__를 이용해 참조하고 있는 prototype의 프로퍼티에 접근할 수 있다!

 

 

 

 

상속 예시

class Human{               //클래스 Human
 constructor(name){
	this.name = name;
    this.arms = 2;
    this.legs = 2;
    }
}

class Baby extends Human {  //Human 을 상속 받은 Baby
  constructor(name){
    super(name);       // Baby class에서 Human constructor의 메서드를 호출하려면 Super mathod 호출해야함
    this.cute = true;  //속성추가
  }
  cry(){               //메서드 추가
	return 'waa waa';
  }
 }

 

prototype은 유전자. 유전자에 기록을 하는 것.

해당 클래스를 상속받는 인스턴스에 직접 접근해 자료를 추가 / 수정하지 않아도,

클래스에만 추가해도 인스턴스에서 사용 가능.

 

인스턴스에서 자료를 조회할 때 일어나는 일 <프로토타입 체인>

1. 인스턴스에서 자료가 조회되면 해당 자료를 출력

2. 인스턴스에 없으면 부모 유전자에서 조회. 없으면 그 위를 또 조회