자바스크립트 JS - OOP - prototype

hyunnu·2021년 4월 12일
0
post-thumbnail

📖Review (21.04.13)

JavaScript는 프로토타입 기반의 언어입니다. 여기서 프로토타입(prototype)은 원형 객체를 의미합니다.
JavaScript의 모든 객체는 prototype이라는 객체를 가지고 있습니다.
모든 객체는 그들의 prototype으로부터 속성과 메소드를 상속받습니다.

prototype chain

Object.prototype 객체는 이러한 프로토타입 체인에서도 가장 상위에 존재하는 프로토타입입니다.

따라서 자바스크립트의 모든 객체는 Object.prototype 객체를 프로토타입으로 상속받습니다.

Human이라는 클래스와 인스턴스, prototype chain

배열 클래스와 인스턴스, prototype chain

prototype의 생성

function Dog(color, name, age) { // 개에 관한 생성자 함수를 작성함.

    this.color = color;          // 색에 관한 프로퍼티

    this.name = name;            // 이름에 관한 프로퍼티

    this.age = age;              // 나이에 관한 프로퍼티

}

var myDog = new Dog("흰색", "복이", 1); // 이 객체는 Dog라는 프로토타입을 가짐.

console.log("우리 집 강아지는 " + myDog.name + "라는 이름의 " + myDog.color + " 털이 매력적인 강아지입니다.");

상속 (inheritance)

  • 상속이란 새로운 class에서 기존 class의 모든 속성과 메소드를 사용할 수 있는 것을 의미한다.
  • JavaScript에서는 현재 존재하고 있는 객체를 프로토타입으로 사용하여, 해당 객체를 복제하여 재사용하는 것을 상속이라고 합니다.

의사 클래스 패턴 상속(Pseudo-classical Inheritance)

의사 클래스 패턴은 자식 생성자 함수의 prototype 속성을 부모 생성자 함수의 인스턴스로 교체하여 상속을 구현하는 방법이다. 부모와 자식 모두 생성자 함수를 정의하여야 한다.

// 부모 생성자 함수
var Parent = (function () {
  // Constructor
  function Parent(name) {
    this.name = name;
  }

  // method
  Parent.prototype.sayHi = function () {
    console.log('Hi! ' + this.name);
  };

  // return constructor
  return Parent;
}());

// 자식 생성자 함수
var Child = (function () {
  // Constructor
  function Child(name) {
    this.name = name;
  }

  // 자식 생성자 함수의 프로토타입 객체를 부모 생성자 함수의 인스턴스로 교체.
  Child.prototype = new Parent(); // ②

  // 메소드 오버라이드
  Child.prototype.sayHi = function () {
    console.log('안녕하세요! ' + this.name);
  };

  // sayBye 메소드는 Parent 생성자함수의 인스턴스에 위치된다
  Child.prototype.sayBye = function () {
    console.log('안녕히가세요! ' + this.name);
  };

  // return constructor
  return Child;
}());
var child = new Child('child'); // ①
console.log(child);  // Parent { name: 'child' }

console.log(Child.prototype); // Parent { name: undefined, sayHi: [Function], sayBye: [Function] }

child.sayHi();  // 안녕하세요! child
child.sayBye(); // 안녕히가세요! child

console.log(child instanceof Parent); // true
console.log(child instanceof Child);  // true

Child 생성자 함수가 생성한 인스턴스 child(①)의 프로토타입 객체는 Parent 생성자 함수가 생성한 인스턴스(②)이다. 그리고 Parent 생성자 함수가 생성한 인스턴스의 프로토타입 객체는 Parent.prototype이다.

생성자 함수를 작성하고 new 연산자를 사용해 객체를 생성하면, 같은 프로토타입을 가지는 객체들을 생성할 수 있습니다.

프로토타입 패턴 상속(Prototypal Inheritance)

프로토타입 패턴 상속은 object.create 함수를 사용하여 객체에서 다른 객체로 직접 상속을 구현하는 방식이다. 프로토타입 패턴 상속은 개념적으로 의사 클래스 패턴 상속보다 더 간단하다. 또한 의사 클래스 패턴의 단점인 new 연산자가 필요없으며, 생성자 링크도 파괴되지 않으며, 객체리터럴에도 사용할 수 있다.

ex 1)

// 부모 생성자 함수
var Parent = (function () {
  // Constructor
  function Parent(name) {
    this.name = name;
  }

  // method
  Parent.prototype.sayHi = function () {
    console.log('Hi! ' + this.name);
  };

  // return constructor
  return Parent;
}());

// create 함수의 인수는 프로토타입이다.
var child = Object.create(Parent.prototype);
child.name = 'child';

child.sayHi();  // Hi! child

console.log(child instanceof Parent); // true

ex 2)

var Bee = require('./Bee');

var HoneyMakerBee = function () {
    Bee.call(this);
    this.age = 10;
    this.job = "make honey";
    this.honeyPot = 0;
};
HoneyMakerBee.prototype = Object.create(Bee.prototype);
HoneyMakerBee.prototype.constructor = HoneyMakerBee;

new 와 object.create()와 차이점

두 방식 모두 새로운 객체를 생성하는 것은 동일하나, 생성 방식은 다르다.

  • new를 사용했을 경우 함수가 생성자로 실행
  • Object.create()의 경우 동일한 객체만 생성하고 생성자는 실행하지 않음

객체에 속성 및 메소드 추가

function Dog(color, name, age) {

    this.color = color;

    this.name = name;

    this.age = age;

}

var myDog = new Dog("흰색", "복이", 1);

myDog.family = "말티푸"; // 품종에 관한 프로퍼티를 추가함.

myDog.breed = function() {        // 털색을 포함한 품종을 반환해 주는 메소드를 추가함.

    return this.color + " " + this.family;

}

console.log("우리 집 강아지는 " + myDog.breed() + "입니다.");

위의 예제에서 새롭게 추가된 weight 프로퍼티와 breed() 메소드는 오직 myDog 인스턴스에만 추가됩니다.

이미 생성된 다른 Dog 객체나 차후에 생성되는 어떠한 다른 Dog 객체에도 추가되지 않습니다.

프로토타입에 속성 및 메소드 추가

프로토타입의 경우에는 생성자 함수에 직접 추가해야만 이후에 생성되는 모든 다른 객체에도 적용할 수 있습니다.

function Dog(color, name, age) {

    this.color = color;

    this.name = name;

    this.age = age;

    this.family = "말티푸"; // 프로토타입에 프로퍼티를 추가할 때에는 기본값을 가지게 할 수 있음.

    this.breed = function() {

        return this.color + " " + this.family;

    };

}

var myDog = new Dog("흰색", "복이", 1);

var hisDog = new Dog("검정색", "꼬미", 3);

console.log("우리 집 강아지는 " + myDog.family + "이고, 친구네 집 강아지도 " + hisDog.family + "입니다.");
profile
Data Engineer / Back-End Developer

0개의 댓글