TIL 99 | 코어자바스크립트(7) 클래스

hyounglee·2021년 1월 3일
2

JavaScript

목록 보기
40/46
post-thumbnail

시대의 명작 코어 자바스크립트를 읽고 자바스크립트 마스터에 도전합니다...

클래스

자바스크립트는 프로토타입 기반 언어라서 '상속' 개념이 존재하지 않는다. 클래스 기반의 언어에 익숙한 많은 개발자들을 혼란케 했고, 이러한 불편함을 해결하기 위해 ES6에는 클래스 문법이 추가되었다. 다만 ES6의 클래스에서도 일정 부분은 프로토타입을 활용하고 있기 때문에, ES5에서 클래스를 흉내내기 위한 구현 방식을 학습하는 것은 큰 의미가 있다.

클래스와 인스턴스의 개념 이해

일반적인 개념으로서의 클래스

음식(superClass) - 과일(subClass/superClass) - 귤류(subClass) - 오렌지(element)
  • 하위클래스는 아무리 구체화되더라도 결국 추상적인 개념일 뿐이다.
  • 오렌지와 같이 어떤 클래스의 속성을 지니는 실존하는 개체를 인스턴스라고 한다.
  • 클래스는 인스턴스들로부터 공통점을 발견하여 정의된다.
  • 하나의 개체가 같은 레벨의 서로 다른 여러 클래스의 인스턴스일 수도 있다.

프로그래밍 언어상의 클래스

  • 사용자가 직접 여러가지 클래스를 정의해야 한다.
  • 클래스를 바탕으로 인스턴스를 만들 때 비로소 어떤 개체가 클래스의 속성을 지닌다.
  • 클래스가 먼저 정의되어야만 그로부터 공통적인 요소를 지니는 개체들을 생성할 수 있다.
  • 한 인스턴스는 하나의 클래스만을 바탕으로 만들어진다. 인스턴스를 생성할 때 호출할 수 있는 클래스는 오직 하나뿐일 수밖에 없기 때문이다.
  • 사용하기에 따라 추상적인 대상일 수도, 구체적인 개체가 될 수도 있다.

자바스크립트의 클래스

자바스크립트는 프로토타입 기반 언어이므로 클래스의 개념이 존재하지 않지만, 프로토타입을 일반적인 의미에서의 클래스 관점에서 접근해보면 비슷하게 해석할 수 있다.

  1. 생성자 함수 Array를 new 연산자와 함께 호출하면 인스턴스가 생성된다.
  2. 이때 Array를 일종의 클래스라고 한다면, Array의 prototype 객체 내부의 요소들이 인스턴스에 상속된다고 볼 수 있다. (엄밀히는 상속이 아닌 프로토타입 체이닝에 의한 참조)
  3. 한편 Array 내부 프로퍼티들 중 prototype 프로퍼티를 제외한 나머지는 인스턴스에 상속되지 않는다.

인스턴스에 상속되는지(인스턴스가 참조하는지) 여부에 따라 스태틱 멤버인스턴스 멤버로 나뉜다.

자바스크립트에서는 인스턴스에서도 직접 메서드를 정의할 수 있기 때문에 혼란을 야기할 수 있어서 인스턴스 메서드 대신에 프로토타입 메서드라고 부르는게 좋다.

// 생성자
var Rectangle = function(width, height) {
    this.width = width;
    this.height = height;
}

// (프로토타입) 메서드
Rectangle.prototype.getArea = function() {
    return this.width * this.height;
}

// 스태틱 메서드
Rectangle.isRectangle = function(instance) {
    return instance instanceof Rectangle && instance.width > 0 && instance.height > 0
}

var rect1 = new Rectangle(3,4)
console.log(rect1.getArea());	// 12 (O)
console.log(rect1.isRectangle(rect1)); 	//  Error (X)
console.log(rect1.Rectangle.isRectangle(rect1)); // true
  • 프로토타입 메서드는 인스턴스가 마치 자신의 것처럼 호출할 수 있으므로 rect1.__proto__.getArea에 접근하는 것과 같다. 따라서 정상적으로 계산값이 반환된다. 이렇게 인스턴스에서 직접 호출할 수 있는 메서드가 프로토타입 메서드이다.
  • 인스턴스가 isReactangle라는 메서드에 접근하고자 하지만rec1에 해당 메서드는 없고, rect1.__proto__에도 없으며, rect1.__proto__.__proto__에도 없다. 결국 함수가 아니어서 실행할 수 없다는 에러가 발생한다.
  • 이렇게 인스턴스에서 직접 접근할 수 없는 메서드를 스태틱 메서드라고 한다. 스태틱 메서드는 마지막 콘솔처럼 생성자 함수를 this로 해야만 호출이 가능하다.

클래스 상속

클래스 상속을 흉내내기 위한 세가지 방법

즉, 클래스(prototype)이 구체적인 데이터를 지니지 않게 하는 방법...

  1. subClass.prototypesuperClass의 인스턴스를 할당한 다음 프로퍼티를 모두 삭제하는 방법
  2. 빈 함수(Bridge)를 활용하는 방법
  3. Object.create를 이용하는 방법

ES6의 클래스 및 클래스 상속

이전까지는 상속 및 추상화를 구현하기 위해 상당히 복잡한 방법을 사용했으나, ES6에서는 클래스 문법이 도입되어 상당히 간단하게 처리된다.

ES5와 ES6의 클래스 문법 비교

// ES5

var ES5 = function (name) {
  this.name = name;
};
ES5.staticMethod = function () {
  return this.name + ' staticMethod';
};
ES5.prototype.method = function () {
  return this.name + ' method';
};
var es5Instance = new ES5('es5');
console.log(ES5.staticMethod()); // es5 staticMethod
console.log(es5Instance.method()); // es5 method
// ES6

var ES6 = class {
  constructor (name) {
    this.name = name;
  }
  static staticMethod () {
    return this.name + ' staticMethod';
  }
  method () {
    return this.name + ' method';
  }
};
var es6Instance = new ES6('es6');
console.log(ES6.staticMethod()); // es6 staticMethod
console.log(es6Instance.method()) // es6 method
  • class 라는 명령어 뒤에 바로 { } 가 등장하는데, 이 중괄호 묶음의 내부가 클래스 본문 영역이다.
  • constructor라는 이름 뒤에 바로 ( ) { 가 등장한다. 클래스 본문에서는 function 키워드를 생략하더라도 모두 메서드로 인식한다. 이름처럼 ES5의 생성자 함수와 동일하다.
  • 메서드와 다음 메서드 사이는 콤마로 구분하지 않는다.
  • static 키워드로 시작하는 메서드는 ES5에서 생성자 함수에 바로 할당하는 메서드와 동일하게 생성자 함수(클래스)만이 호출할 수 있다.
  • method가 바로 나오는 부분은 자동으로 prototype 객체 내부에 할당되는 메서드이다. ES5.prototype.method와 동일하게 인스턴스가 프로토타입 체이닝을 통해 마치 자신의 것처럼 호출할 수 있는 메서드이다.
profile
(~˘▾˘)~♫❝ 쉽게만 살아가면 재미없어 빙고 .ᐟ ❞•*¨*•.¸¸♪

0개의 댓글