클래스

클래스란 연관 있는 데이터(fields, methods)를 한 군데 묶어놓는 컨테이너 역할을 한다.

클래스 안에서도 내부에서만 사용가능한 변수와 외부에서 보일 수 있는 변수를 구분짓는 캡슐화(Encapsulation)가 가능하다.

클래스는 상속과 다형성이 일어날 수 있다.

이 모든 것은 기본적으로 객체지향언어 여야 가능하다는 점! 잊지 말자.

클래스란?

  • 붕어빵 틀로 비유할 수 있다
  • 한번만 선언된다
  • 실질적인 데이터는 들어가지 않는다
  • 메모리에 올라가지 않는다

오브젝트란?

  • 붕어빵 틀을 이용해서 구워진 붕어빵을 생각하자
  • 여러 개 생성될 수 있다
  • 데이터가 들어있다
  • 실질적으로 메모리에 올라간다
  • 인스턴스 라고 부를 수 있다

자바스크립트에서의 클래스는 ES6에 추가되었다. 이전에는 함수를 사용해서 템플릿을 만들었었다.

클래스는 기존의 프로토타입을 기반으로 해서 클래스 문법만 추가된 것(syntactic sugar)

  1. 클래스 선언
class Person { 
	//constructor 
  constructor(name, age) {
    // fields
    this.name = name;
    this.age = age;
  }
  
  // methods
  speak() {
    console.log(`${this.name}: hello!`)
  }
}

const kim = new Person('jinhyuck', 29)
console.log(kim.name) // 'kim'
console.log(kim.age) // 29
  1. Getters and setters
// getter & setter는 값의 상하한선을 정해줄 때 쓴다
class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
  }
}

const user1 = new User('steve', 'jobs', -1)
console.log(user1.age) // -1 -> 나이는 -1이 될 수 없다

class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age // 여기서 this.age는 get함수로 간다. 그 후 set으로 가서 값을 가지고 대입한다
		// 값인 age는 get() -> set()의 전달인자 -> get()리턴 -> this.age에 저장 순으로 간다
  }
  
  get age() {
    return this._age
  }
  set age(value) {
    // 값을 검사하는 부분
    if (value < 0) {
      throw Error('나이는 0 보다 작을 수 없습니다.')
    }
    this._age = value
  }
}

  1. Fields (public, private)
// 가장 최근에 추가된 부분. 쓰려면 바벨을 사용해야 한다
class Experiment {
  publicField = 2;
#privateFIeld = 0;
// #를 붙이면 private하게 사용됨. 클래스 외부에서는 사용이 불가능
}

const experiment = new Experiment()
console.log(experiment.publicField) // 2
console.log(experiment.privateField) // undefined
  1. Static properties and methods
// 인스턴스가 아닌 클래스 자체에 연결되어 있는 필드 또는 메서드
// 오브젝트에 상관없이, 들어오는 데이터에 상관없이 공통적으로 클래스에서 사용되는 것이라면
// 스태틱을 사용해서 메모리의 낭비를 줄일 수 있다
// 타입스크립트에서도 많이 쓰임
class Article {
  static publisher = 'Kim'
	constructor(articleNumber) {
    this.articleNumber = articleNumber
  }
	
	static printPublisher() {
    console.log(Article.publisher)
  }
}

const article1 = new Article(1)
console.log(aritcle1.publisher) // undefined
console.log(Article.publisher) // 'Kim'
Article.printPublisher() // 'Kim'

상속

여러 모듈이 공통적인 속성을 가질 경우 쉽게 재사용할 수 있다

class Shape {
  constructor (width, height, color) {
    this.width = width
    this.height = height
    this.color = color
  }
  
  draw() {
    console.log(`draw ${this.color} color`)
  }
  
  getArea() {
    return this.width * this.height
  }
}

class Rectangle extends Shape {}
const rectangle = new Rectangle(20, 20, 'blue')
rectangle.draw() // draw blue color
retangle.getArea() // 400

class Triangle extends Shape {
  // 오버라이딩 가능!
  draw() {
    super.draw() // 부모함수의 draw 메서드를 실행
    console.log('triangle!')
  }
  getArea() {
    return (this.width * this.height) / 2;
  }
}
const triangle = new Triangle(20, 20, 'red')
triangle.draw() // draw red color triangle!
triangle.getArea() // 200

// Class checking: instanceOf
console.log(rectangle instanceof Rectangle) // true
console.log(triangle instanceof Rectangle) // false
console.log(triangle instanceof Triangle) // true
console.log(triangle instanceof Shape) // true
console.log(triangle instanceof Object) // true 
// 자바스크립트에서 만든 모든 오브젝트는 오브젝트 클래스를 자동으로 상속받는다. 
// cmd+click으로 오브젝트가 정의된 부분으로 이동할 수 있다!