자바스크립트 핵심컨샙33(+ES6) #14. Factories and Classes(팩토리와 클래스)

20026 단어 ES6JavaScriptES6

자바스크립트의 객체지향 프로그래밍을 알아봅시다!


0. 생성자 함수

자바스크립트에서 인스턴스를 생성하는 가장 기본적인 방법인 생성방법이다. 다른 포스트에서 다룬적이 있다.

function Func(a, b) { 
  	this.a = a;
    this.b = b; 
}
Func.prototype.meth = function(){
	console.log(this.a + this.b)
}
  
var inst = new Func(1, 2)

하도 많이 다뤘으니 자세한 설명은 생략하고 다른 포스트를 보자


1. 팩토리 함수

function Func(a, b) { 
    var obj = {}
    obj.a = a;
    obj.b = b;
  	obj.meth = function(){
		  console.log(this.a + this.b)
    }
  
  	return obj
}
  
var inst01 = Func(1, 2);
var inst02 = Func(3, 4);

inst01.meth()//3
inst02.meth()//7
  • 팩토리 함수는 객체를 반환하는 클래스나 생성자가 아닌 일반함수입니다!
  • JS에서는 모든 함수가 객체를 반환 할 수 있다는 특징을 이용하여 작성하는 새로운 디자인 패턴입니다.
  • 일반 생성자 함수와 달리 new 키워드가 없다는게 특징입니다.

2. 클래스

ES6에 추가된 문법입니다! 자바나 다른 언어의 클래스가 아닙니다!

2_1. 자바스크립트에서의 클래스

객체지향의 중심인 클래스를 자바스크립트에서 알아봅시다.

class Func{
	constructor(a, b) {//(4.)
      this.a = a;
      this.b = b;
    }
  
  	meth(){
    	console.log(this.a + this.b)
    }
}

Func.c = 20;//(5.)
Func.prototype.d = 25;

const inst = new Func(1, 2);

이전의 생성자, 팩토리 함수와 같은 결과를 도출하지만 문법적으로 훨씬 깔끔해졌습니다. 기존의 변수들은 constructor라는 메서드에 넣고 기존 메서드들은 바깥에 작성합니다. 자바스크립트에 추가된 새로운 기능입니다. 하지만 그렇다고 해서 JS가 클래스를 지원하는것은 아닙니다?

console.log(typeof Func)// function (1.)
console.log(Func === Func.prototype.constructor)//true(2.)
console.log(Func.prototype)//Func{} 메서드 안나옴(3.)

클래스 문법 구조가 진짜 하는 일은 다음과 같습니다.

    1. 우선 자바스크립트에서 클래스는 함수의 한 종류입니다.
    1. Func라는 이름을 가진 함수를 만듭니다. 함수 본문은 생성자 메서드 constructor에서 가져옵니다(변수들 같은거). 생성자 메서드가 없으면 본문이 비워진 채로 함수가 만들어집니다.
    1. meth같은 메서드를 Func.prototype에 저장합니다. 하지만 클래스 메서드는 열거할 수 없습니다ㅠ
    1. 인스턴스 속성은 반드시 클래스 메서드 내에 정의되어야 합니다
    1. 정적 (클래스사이드) 속성과 프로토타입 데이터 속성은 반드시 클래스 선언부 바깥쪽에서 정의되어야 합니다.

2_2. 🤔생성자 함수와의 차이점

하지만 이전에 다뤘던 생성자함수를 통해 인스턴스를 생성했던 방법과 크게 다르지않습니다. 하지만 중요한 차이가 몇가지 있습니다.

console.log(Func)//console.log(Func)(2.)
    1. class로 만든 함수엔 특수 내부 프로퍼티인 [[FunctionKind]]:"classConstructor"가 이름표처럼 붙습니다. 자바스크립트는 다양한 방법을 사용해 함수에 [[FunctionKind]]:"classConstructor"가 있는지를 확인합니다. 이런 검증 과정이 있기 때문에 클래스 생성자를 new와 함께 호출하지 않으면 에러가 발생합니다.
    1. 대부분의 자바스크립트 엔진이 클래스 생성자를 문자열로 표현할 때 'class…'로 시작하는 문자열로 표현한다는 점 역시 다릅니다.
    1. 클래스 메서드는 열거할 수 없습니다(non-enumerable)(위에서 봤던것 처럼)
    1. 클래스는 항상 엄격 모드로 실행됩니다(use strict)
    1. 함수 선언과 클래스 선언의 차이점은 함수 선언의 경우 호이스팅이 일어나지만, 클래스 선언은 그렇지 않다는 것입니다.

2_3. Static

static 키워드는 클래스를 위한 정적(static) 메서드를 정의합니다. 정적 메서드는 클래스의 인스턴스화(instantiating) 없이 호출되며, 클래스의 인스턴스에서는 호출할 수 없습니다.

class Func{
	constructor(a, b) {
      this.a = a;
      this.b = b;
    }
  
    static meth01 = "method";

  	static meth02(){
    	console.log(this.a + this.b)
    }
}

const inst = new Func(1, 2);

console.log(inst.meth01)//언디파인드
console.log(inst.meth02)//언디파인드

2_4. extend

클래스에서의 "상속"기능은 어떻게 사용되는지 확인해보겠습니다. 객체지향 프로그래밍의 중요한 점 중 하나입니다.

class Func{
	constructor(a, b) {
      this.a = a;
      this.b = b;
    }
  	meth01(){
    	console.log(this.a + this.b)
    }
}

class Child extends Func{
  	constructor(c) {
      this.c = c;
    }
  	meth01(){;
    	console.log("override")
    }
  	meth02(){
    	console.log(`${this.a} is ${this.b}`)
    }
}

const inst = new Child(1, 2);

inst.meth01()//override
inst.meth02()//error

프로토타입의 상속과 같은 결과를 도출합니다. 프로토타입의 상속은 Object.create쓰고 뭐 여러가지 해야할게 많았지만 class의 extend를 사용하니 훨씬 가독성이 좋아졌습니다.

여기서 만약 자식클래스에 동일명의 메서드가 존재하면 부모 클래스의 메서드에서 덮어씌어집니다.
이것을 메서드 오버라이딩이라고 합니다. 만약 부모의 메서드를 사용하고 싶을땐 super를 사용합니다.

  	meth01(){;
        super.meth01()
    	console.log("override")
    }

그리고 inst.meth02()를 호출하면 a, b가 존재하지않는다고 에러가 발생합니다. 에러문을 보면 자식 클래스에서 constructor를 호출할때 부모생성자를 반드시 호출해야한다고 나옵니다. 그리고 부모 constructor의 인수를 사용하려면 자식 constructor에서 부모 인수를 받아와야합니다.(아복잡다)

  constructor(a, b, c) {
    super(a, b);
    this.c = c;
  }

그런데 constructor를 만들지 않고 자식 클래스를 생성할 수도 있습니다. 그런 경우는

  constructor(...arg) {
    super(...arg);
  }

이런 모양이 자동으로 생성됩니다.

좋은 웹페이지 즐겨찾기