모던 자바스크립트 Deep Dive - 9

2023. 4. 10. 11:43개발 관련 책 읽기/모던 자바스크립트 Deep Dive

✅ 아래 내용들에 대해서 알아보자

- 프로토타입

 

 

프로토타입

JS는 프로토타입 기반으로 상속을 구현하여 불필요한 중복을 제거한다. 다음 코드를 보자

아래 코드 실행 시 JS에서는 인스턴스 생성 시 동일한 메서드를 중복으로 생성하여 비효율적인 방식으로 생성한다.

 

function Circle(radius) {
    this.radius = radius;
    this.getArea = function () {
        return Math.PI * this.radius ** 2;
    }
}

const circle1 = new Circle(1);
const circle2 = new Circle(2);


/**
 * Circle 생성자 함수는 인스턴스 생성할 때마다 동일한 동작하는 getArea 메서드를 중복 생성하고 모든 인스턴스가 중복 소유한다.
 * getArea 메서드는 하나만 생성하여 모든 인스턴스가 공유해서 사용하는 것이 바람직하다.
 */
console.log(circle1.getArea === circle2.getArea);   //false

console.log(circle1.getArea());
console.log(circle2.getArea());

 

 

 

 

위의 동일한 메서드를 각 객체마다 중복으로 생성하는 문제점을  해결해 보자.

아래 코드를 보면 프로토타입(Circle.prototype.)을 사용해서 상속으로 메서드를 공유하게 된다.

 

Circle 생성자 함수가 생성한 모든 인스턴스는 부모 객체 역할을 하는 Circle, prototype의 모든 프로퍼티와 메서드를 상속받게 된다.

getArea 메서드느 Circle.prototpye의 모든 프로퍼티와 메서드를 상속받게 되고, 모든 인스턴스는 getArea메서드를 공유하여 사용할 수 있게 된다.  

/**
 * 생성자 함수
 */
function Circle(radius){
    this.radius=radius;
}

/**
 *  Circle 생성자 함수가 모든 인스턴스가 getArea 메서드를 공유해서 사용할 수 있도록 프로토타입에 추가한다.
 *  프로토타입은 Circle 생성자 함수의 prototype 프로퍼티에 바인딩되어 있다.
 */
Circle.prototype.getArea = function (){
    return Math.PI * this.radius ** 2;
};

//인스턴스 생성
const circle1 = new Circle(1);
const circle2 = new Circle(2);

/**
 * Circle 생성자 함수가 생성한 모든 인스턴스는 부모 객체의 역할을 하는
 * 프로토 Circle.prototype으로부터 getArea 메서드를 상속받는다.
 *
 * 즉, Circle 생성자 함수가 생성하는 모든 인스턴스는 하나의 getArea를 공유한다.
 */
console.log(circle1.getArea === circle2.getArea);   //true

console.log(circle1.getArea());
console.log(circle2.getArea());

 

 

 

 

프로토타입 객체

 프로토타입 객체란 OOP근간을 이루는 객체 간 상속을 구현하기 위해 사용된다.

 

프로토타입은 어떤 객체의 상위 객체의 역할을 하는 객체로 다른 객체에 공유 프로퍼티(메서드 포함)을 제공한다.

상속받은 하위 객체는 상위 객체의 프로퍼티를 자유롭게 사용할 수 있게 된다.

 

모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조다.

객체가 생성될 떄 객체의 생성 방식에 따라 프로토타입이 결정되고 [[Prototype]]에 저장된다.

 

모든 객체는 하나의 프로토타입을 가지며, 모든 프로토타입은 생성자 함수와 연결되어 있다.

즉, 객체와 프로토타입과 생성자 함수는 연결되어 있다. 아래 그림을 보자

 

 

 

프로토타입 접근 방법

  1. 객체는  __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, [[Prototype]] 내부 슬롯이 가리키는 프로토타입에 간접 접근할 수 있다.
  2. 프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있다.
  3. 그리고 생성자 함수는 자신의 prototype 프로퍼티를 통해 프로퍼티타입에 접근할 수 있게 된다.

 

 

 

__proto__ 접근자 프로퍼티를 직접사용해서 접근하는 방식을 권장하지 않는다.

따라서, 아래 코드처럼 getPrototypeOf(), setPrototypeOf()를 사용해서 프로토타입을 제어해야 한다.

const parent = {x:1};

//obj 객체의 프로토타입 취득
Object.getPrototypeOf(obj);

//obj 객체의 프로토타입 교체
Object.setPrototypeOf(obj, parent);

console.log(obj.x); //1

 

 

 

함수 객체의 prototype 프로퍼티

 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.

//함수 객체는 prototype 프로퍼티를 소유한다.
console.log((function () {}).hasOwnProperty('prototype'));   //true

//일반 객체는 prototype 프로퍼티를 소유하지 않는다.
console.log(({}).hasOwnProperty('prototype'));   //false
반응형