본문 바로가기
JavaScript

new 연산자로 재사용성 높이기

by Vintz 2021. 11. 1.
반응형

new 연산자와 생성자 함수

new 연산자는 사용자 정의 객체 타입 또는 내장 객체 타입의 인스턴스를 생성한다. - MDN

MDN에서 설명하는 new 연산자다.

 

여기서 설명하는 '사용자 정의 객체'와 '객체 타입의 인스턴스 생성'에 대해 알아보자.

 

객체 리터럴 {...}을 사용하면 객체를 쉽게 만들 수 있다. 하지만 유사한 객체를 여러 개 만들 경우엔 new 연산자와 생성자 함수를 사용하면 유사한 객체 여러 개를 쉽게 만들 수 있다. 예를 들어 복수의 사용자, 메뉴 내 다양한 아이템을 객체로 표현할 경우에 유용하다.

생성자 함수

생성자 함수는 다음과 같은 관계를 따른다.

  1. 함수 이름의 첫 글자는 대문자로 시작한다
  2. 반드시 new 연산자를 붙여 실행한다.

예시

function User(name) {
  // this = {}; 빈 객체가 암시적으로 만들어진다
  
  // 새로운 프로퍼티를 this에 추가
  this.name = name;
  this.isAdmin = false;
  
  // return this; this가 암시적으로 반환됨
}

const user = new User("Vintz");

console.log(user.name); // Vintz
console.log(user.isAdmin); // false

위 예시에서 new User(...)를 써서 함수를 실행하면 아래와 같은 알고리즘이 동작한다.

  1. 빈 객체를 만들어 this에 할당한다.
  2. 함수 본문을 실행한다.
  3. this에 새로운 프로퍼티를 추가해 this를 수정한다.
  4. this를 반환한다.

그럼 이제 const user = new User("Vintz")는 아래 코드를 입력한 것과 동일하게 동작한다.

const user = {
  name: "Vintz",
  isAdmin: false
};

이 외에도 new User(...)를 이용하면 다양한 이름의 '사용자 정의 객체'를 손쉽게 만들 수 있다. 객체 리터럴 {...} 문법으로 일일이 객체를 만드는 방법보다 훨씬 간단하고 읽기 쉽게 객체를 만들 수 있게 되었다.

 

생성자의 의의는 바로 여기에 있다. 재사용 가능한 객체 생성 코드를 구현하는 것이다.

 

따라서 생성자가 하는 일은 객체에 대한 초기화라는 것을 알 수 있다. 즉, 객체에 대해 초기 설정을 해놓고 해당 객체의 프로퍼티와 메서드로 유사한 독립적인 객체를 손쉽게 만들 수 있다.

  1. 함수를 작성하여 객체 타입(객체의 이름과 속성)을 정의한다. -> 사용자 정의 객체
  2. new 연산자로 객체의 인스턴스를 생성한다. -> 객체 타입의 인스턴스 생성

이제 어느정도 알게 된 것 같다. 좀 더 익히기 위해 new 연산자로 간단한 Pagination을 구현해보자.

new 연산자로 Pagination 구현하기

먼저 기본적인 프로퍼티를 정의 해보자.

  • currentPage : 현재 페이지, 기본값은 1로
  • pagePerItems: 페이지당 아이템들, 기본값은 5로
  • totalPage: 전체 페이지, 기본값은 20으로
function Pagination({ currentPage, pagePerItems, totalPage }) {
  this.currentPage = currentPage || 1;
  this.pagePerItems = pagePerItems || 5;
  this.totalPage = totalPage || 20;
}

이렇게 프로퍼티와 프로퍼티의 기본값이 정의되었다. 그럼 이제 객체를 생성 해보자.

const pagination = new Pagination({
  currentPage: 2,
  pagePerItems: 10,
  totalPage: 8,
});

const pagination2 = new Pagination({
  currentPage: 5,
  totalPage: 25,
});

console.log(pagination);
console.log(pagination2);

여기서 주의할 점은 생성자 함수에 파라미터를 객체 타입으로 넘겨주었고, 서로 다른 독립적인 객체들이 생성 됐다는 점이다. 이렇게 한번 정의해두면 손쉽게 유사한 객체들을 만들 수 있다.

서로 다른 상태의 Pagination 객체

이번엔 사용자 정의 컴포넌트처럼 만들어 보자. 먼저 상태를 정의하고, 새로운 상태로 바꿔주는 setState 메서드, 그리고 render 메서드까지 구현해야 한다.

function Pagination({ currentPage, pagePerItems, totalPage }) {
  this.state = {
    currentPage: currentPage || 1,
    pagePerItems: pagePerItems || 0,
    totalPage: totalPage || 20,
  };

  this.setState = (newState) => {
    this.state = {
      ...this.state,
      ...newState,
    };
    this.render();
  };

  this.render = () => {
    const app = document.querySelector('#app');
    app.innerHTML = `
      <span><i class="fas fa-chevron-left"></i></span>
      ${Pages(this.state)}
      <span><i class="fas fa-chevron-right"></i></span>
    `;
  };
}

const Pages = ({ totalPage, currentPage }) => {
  const pages = [];
  let index = 1;

  while (totalPage >= index) {
    pages.push(`<span>${index}</span>`);
    index++;
  }

  if (totalPage > currentPage) {
    pages[currentPage - 1] = `<span class="show">${currentPage}</span>`;
  } else {
    pages[pages.length - 1] = `<span class="show">${pages.length}</span>`;
  }

  return pages.join('');
};

이제 객체를 만들고 렌더를 해보자.

const pagination = new Pagination({
  currentPage: 7,
  pagePerItems: 0,
  totalPage: 10,
});

pagination.render();

렌더링 결과1

setState 함수로 기존 상태를 바꿀 수도 있다.

const pagination = new Pagination({
  currentPage: 7,
  pagePerItems: 0,
  totalPage: 10,
});

pagination.setState({
  currentPage: 9,
});

렌더링 결과2

 

반응형