오늘은 클래스에 대해 알아보도록 한다.

원래 자바스크립트 언어는 우리를 힘들게 하는 프로토타입 기반의 언어이다. 하여 이전 ES5에서는 프로토타입을 통해 생성자 함수와 객체지향 언어를 구현할 수 있었다!

이후 등장한 클래스(aka. 붕어빵틀)는 생성자 함수와 매우 유사하게 동작한다.
하지만 우리가 알아야 할 몇가지 차이점이 있다!

  1. 클래스를 new 연산자 없이 호출하면 에러 발생!
  2. 클래스는 상속을 가능케하는 extends와 super키워드를 제공한다. (생성자 함수는 그렇지 못함)
  3. 클래스는 호이스팅이 발생하지 않는 것처럼 동작함! (하지만 사실 됨)
  4. 클래스 코드 내 암묵적으로 strict mode가 실행됨
  5. 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false임

클래스는 생성자 함수 보다 견고하고 명료하다(하지만 우월하진 않다, 상황에 따라 다르게 사용!) "객체를 만드는 새로운 방법"이라고 생각하자

클래스를 정의하는 방법

//클래스 선언문
class 붕어빵틀 {}

//클래스 표현식 (익명) 
const 붕어빵틀 = class {}; 
//클래스 표현식 (기명) 
const 붕어빵틀 = class MyClass {}; 

지난번에 알아본 함수와 같이 클래스도 일급 객체이다! 그래서..
1. 런타임에 생성이 가능하다
2. 변수나 자료구조(배열, 객체 등)에 저장할 수 있다
3. 함수의 반환값으로 사용 가능하다

클래스의 호이스팅

class 붕어빵틀 {}
console.log(typeof 붕어빵틀); // function 

클래스는 함수로 평가된다 (typeof 찍었을 때).
선언문은 런타임 이전에 먼저 평가되어 함수 객체를 생성한다.


클래스 선언문으로 클래스를 만든 경우, 런타임 이전에 평가되어서 함수 객체를 생성하는데.. 여기서의 함수 객체는 생성자함수로 호출할 수 있는 constructor이다.
이와 동시에 프로토타입도 함께 생겨난다고 한다..!

여기서 논란의 호이스팅 문제

console.log(잉어빵틀); // 선언하기 전 참조 안되는것 처럼 보임  
class 잉어빵틀 {}

참조에러로 호이스팅 안되는 것 처럼 보이지만 let const 와 같은 변수처럼 호이스팅이 된다. 일시적 사각지대에 빠져 호이스팅이 발생하지 않는 것처럼 동작하는 것이다.

인스턴스 생성

//되는 것 (일반적인 방법) 

class 붕어빵틀 {}

//인스턴스 만들기 
const 팥붕어빵 = new 붕어빵틀();
console.log(팥붕어빵); // 붕어빵틀 출력 


//안되는 것 (에러발생) 
// 기명 클래스 표현식의 클래스 이름을 사용해 인스턴스를 생성하면 에러가 생긴다 

const 팥붕어빵 = class 붕어빵틀 {}; 
const 슈붕어빵 = new 팥붕어빵 {}; 

console.log(붕어빵틀); 
const 녹차붕어빵 = new 붕어빵틀(); 

메서드

클래스의 몸체에는세 가지 메서드를 정의할 수 있다.

1. constructor

constructor는 인스턴스를 생성하고 초기화하기 위한 특수한 메서드!

class Jiyun {
  //생성자
  constructor(name) {
    //인스턴스 생성 및 초기화
    this.name = name; 
  }
}

const person = new Jiyun('marie');
console.dir(person); 

클래스 내부의 prototype 프로퍼티 안 constructor 프로퍼티가 있고, constructor는 자신을 가리키고 있다.

놀라운 사실:
*클래스의 constructor 메서드와 프로토타입의 constructor 프로퍼티는 직접적인 관련이 없다. (?????)
프로토타입의 constructor 프로퍼티는 생성자 함수를 가리킨다.

우리가 기억 할 것:

  1. constructor는 클래스 내 한개만 존재할 수 있다. (두개 만들면 문법에러 발생)
  2. constructor는 생략이 가능하다. (constructor 암묵정으로 정의됨)
class Banana {
  constructor(){
  }
}
const apple = new Banana(); 
console.log(apple); //Banana {} 
//위처럼 빈객체를 생성함!!!
  1. constructor를 통해 초기값을 전달한다
class Room {
	constructor(chair, table){
      this.chair = chair; 
      this.table = table; 
    }
}

const myroom = new Room('red', 'blue'); 
console.log(myroom); 

2. 프로토타입 메서드

// 생성자 함수 
function Jiyun(name){
  this.name = name;
}

Jiyun.prototype.sayHi = function () {
  console.log(`Hi my name is ${this.name}`);
};

const jiyunone = new Jiyun('june'); 
jiyunone.sayHi();

3. 정적 메서드

 class Room {
	constructor(chair, table){
      this.chair = chair; 
      this.table = table; 
    }
}

Room.sayColor = function() {
	console.log('Hi!'); 
}; 

// 정적 메서드 호출 
Room.sayColor(); // Hi 
  

프로토타입 메서드? 정적 메서드? 기억할 것

  1. 속해 있는 프로토타입 체인이 다르다
  2. 정적 메서드는 클래스로 호출하고 프로토타입 메서드는 인스턴스로 호출한다.
    *인스턴스: 클래스를 기반으로 만든 객체
  3. 정적 메서드는 인스턴스 프로퍼티 참조 불가! 프로토타입 메서드는 가능!
class Square {
  constructor(width, height){
    this.width = width; 
    this.height = height; 
  }
  //프로토타입 메서드
  area() {
    return this.width * this.height; 
  }
}

const square = new Square(10, 10); 
console.log(square.area()); // 100 
profile
the best is yet to come

0개의 댓글

관련 채용 정보