• Home
  • About
    • Jiwon Jeong photo

      Jiwon Jeong

      끊임없이 배우며 성장하는 엔지니어

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags
    • All Categories
  • Projects

객체 생성자 패턴

24 May 2021

Reading time ~3 minutes

자바스크립트 객체 다시 이해하기

var healthObj = {
  name : "crong",
  lastTime : "PM10:12",
  showHealth : function() {
    console.log(this.name + "님, 오늘은 " + this.lastTime + "에 운동을 하셨네요");
  }
}

healthObj.showHealth();

자바스크립트의 프로토타입 특성 이해

  • 자바스크립트도 객체지향언어임.
  • 그런데, 자바스크립트에는 클래스라는 개념이 없음
    • 대신 프로토타입(Prototype)이라는 것이 존재함. 자바스크립트가 프로토타입 기반 언어라고 불리는 이유
    • 클래스가 없으니 기본적으로 상속기능도 없음. 그래서 보통 프로토타입을 기반으로 상속을 흉내내도록 구현해 사용
    • 참고로 최근의 ECMA6 표준에서는 Class 문법이 추가됨. 하지만 문법이 추가되었다는 것이지, 자바스크립트가 클래스 기반으로 바뀌었다는 것은 아님

객체 동적 생성 - 비슷한 객체를 중복해서 만들고 싶을 때

  • 생성자 함수를 이용한다!
function Health(name, lastTime) {
  this.name = name;
  this.lastTime = lastTime;
    this.showHealth = function(){
        return this.name + "님, 오늘은 " + this.lastTime + "에 운동을 하셨네요"
    }
}
  • 아래와 같이 객체를 만들수 있을까?
    • 결과는 undefined
var obj = Health("crong", "AM 10:10");

객체 동적 생성방법

  • new 키워드 이용!!
    • Health 함수는 new 키워드로 불리면서, 객체를 생성하는 함수 역할 (객체 생성자라고 불림)
var obj1 = new Health("crong", "AM 10:10")

var obj2 = new Health("호눅스", "AM 12:00")

console.log(obj1.showHealth() === obj1.showHealth()) // false
  • obj1.showHealth() 함수와 obj2.showHealth() 함수는 각각 가리키고 있는 메모리 위치가 다르다!

  • 이 때, 생성자들이 프로토타입 이라는것을 가지고 있도록 할 수 있음

    • 프로토타입 안을 들여다보면 같은 지점의 메소드들을 바라보고 있음
    • obj1이 메모리공간에 있는 위치와 obj2가 메모리공간에 있는 위치가 같게 위치시킬 수 있음!

function Health(name, lastTime) {
  this.name = name;
  this.lastTime = lastTime;

}

Health.prototype.showHealth = function(){
   return this.name + "님, 오늘은 " + this.lastTime + "에 운동을 하셨네요"
}
var obj1 = new Health("crong", "AM 10:10")

var obj2 = new Health("호눅스", "AM 12:00")

console.log(obj1.showHealth === obj2.showHealth) // true

  • obj1.showHealth 함수는 obj1 인스턴스의 프로토타입(Health) 안에 들어있는 것을 가리키고 obj2.showHealth 함수 역시 obj2 인스턴스의 프로토타입(Health) 안에 들어있는 것을 가리킴
    • 두 인스턴스의 프로토타입은 Health 함수내에 존재하며, 같은 메모리 공간을 가리키므로 마지막 console이 true를 반환함

  • 다른 예제
function Person() {}

Person.prototype.eyes = 2;
Person.prototype.nose = 1;

var kim  = new Person();
var park = new Person():

console.log(kim.eyes); // => 2

  • kim에는 eyes라는 속성이 없는데도 kim.eyes를 실행하면 2라는 값을 참조
  • kim이 가지고 있는 딱 하나의 속성 __proto__가 그것을 가능하게 해주는 열쇠
    • prototype 속성은 함수만 가지고 있던 것과는 달리 __proto__속성은 모든 객체가 빠짐없이 가지고 있는 속성
    • __proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킴
    • kim객체는 Person함수로부터 생성되었으니 Person 함수의 Prototype Object를 가리키고 있는 것

생각해보기

  1. prototype과 new 키워드를 사용해서 구현할 수 있는 객체지향 자바스크립 코드가 어떤 형태인지?

  2. Prototype Link : __proto__ 라는 속성이 있습니다. 앞선 예제에서 obj1, obj2를 이용해서 obj2.proto 와 같은 식으로 접근해서 결과를 확인해보세요. 직접 쓸 일은 없지만, 내부 prototype 정보를 들여다볼 수 있습니다.

function Health(name, lastTime) {
  this.name = name;
  this.lastTime = lastTime;

}

Health.prototype.showHealth = function(){
   return this.name + "님, 오늘은 " + this.lastTime + "에 운동을 하셨네요"
}
var obj1 = new Health("crong", "AM 10:10")

var obj2 = new Health("호눅스", "AM 12:00")

console.log(obj2.__proto__) // {showHealth: ƒ, constructor: ƒ}

  • 다른 예제
    • __proto__를 사용하여 다른 객체 상속 받기
    • 아래의 예제에서 subObj가 superObj 객체를 상속받는다 (2번 결과)
      • 즉, 위의 prototype과 같은 효과를 나타낸다
    • subObj 객체로 superVal 를 바꿔도 반영이 되지 않는다 (3번 결과)
var superObj = {superVal:'super'}
var subObj = {subVal:'sub'}

subObj.__proto__ = superObj;

console.log(subObj.subVal); // 1. sub
console.log(subObj.superVal); // 2. super 

subObj.superVal = 'sub';
console.log('superObj.superVal =>', superObj.superVal); // 3. super
  1. Object.create 를 사용해서도 클래스와 같은 코드를 만들 수 있습니다. ES6에서는 Class라는 키워드가 존재합니다. 어떻게 클래스를 만들고 메서드를 추가할 수 있는지 예제를 찾아서 확인해보세요. 많은 framework들이 이런 패턴으로 컴포넌트를 만들고 있습니다. 그런데 ES6 Class도 결국은 prototype을 활용해서 클래스구조를 생성한답니다. 따라서 prototype에 대한 이해는 자바스크립트를 이해하는데 꼭 알아둬야 할 개념입니다.
class Food {
  constructor(name) {
    this.name = name;
    this.brands = [];
  }

  addBrand(brand) {
    this.brands.push(brand);
  }

  print() {
    console.log(`${this.name}을 파는 음식점들`);
    console.log(`[ ${this.brands.join(",")} ]`);
  }
}

class Chicken extends Food {
  constructor() {
    super("치킨");
  }
}

class Pizza extends Food {
  constructor() {
    super("피자");
  }
}

const pizza = new Pizza();
pizza.addBrand("피자헛");
pizza.addBrand("도미노피자");
pizza.addBrand("오구쌀피자");

const chicken = new Chicken();
chicken.addBrand("굽네치킨");
chicken.addBrand("교촌치킨");
chicken.addBrand("왕천파닭");

pizza.print(); 
chicken.print();

// 피자을 파는 음식점들
// [ 피자헛,도미노피자,오구쌀피자 ]
// 치킨을 파는 음식점들
// [ 굽네치킨,교촌치킨,왕천파닭 ]

관련 링크

  • https://opentutorials.org/module/4047/24626

  • https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

  • https://blog.naver.com/nebi25/221749567662

  • https://medium.com/@han7096/javascript-core-3-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-prototype-c2da4c24820e



WebProgramming Share Tweet +1