프리온보딩 코스 세 번째 과제

YUZAMIN
Hello, World! I'm YUZAMIN, a diligently endeavoring frontend developer 🐤💦
프리온보딩 코스 세 번째 과제

Class가 뭘까?🙄

세번째 과제를 수행할 때 다른 팀원분이 class를 사용하여 코드를 짠 것을 보고 굉장히 편리하다는 생각이 들었고, 이참에 한번 자바스크립트에서 클래스를 사용하는 법을 명확하게 알아봐야겠다는 생각을 했다.

왠지 어렵게만 느껴져서 미뤄왔던 클래스 공부, 이번 기회에 잡고 가자👊🏻

Class 정의

  • 객체 생성을 위한 템플릿이자, ‘특별한 함수’
1
2
3
4
5
class Human {}

const kim = new Human()
console.log(kim)
// Human {}
  • class 키워드로 클래스 객체를 생성할 수 있음
  • class로 만든 Human이라는 객체가 생성됨
1
2
3
4
5
6
7
8
9
class Square {
  constructor(height, width) {
    this.height = height
    this.width = width
  }
  sayHi() {
    alert(this.name)
  }
}
  • 이 구조가 의미하는 바는

    • Square라는 이름의 함수를 만듦. 함수의 본문은 생성자 메소드인 constructor에서 가져옴(없으면 본문이 비워진 채 함수가 생성됨).
    • sayHi와 같은 메소드는 Sqaure.prototype에 저장함.
    • new Square를 호출해서 객체를 만든 후, 객체의 메소드를 호출하면 해당 메소드를 프로토타입에서 가져옴
  • 데이터 + 그 데이터를 조작하는 코드 = 클래스

Class 선언

  • 클래스를 정의하는 방법
  • Class keyword + Class name
  • ex)
1
2
3
4
5
6
class Square {
  constructor(height, width) {
    this.height = height
    this.width = width
  }
}
  • 클래스 선언과 함수 선언의 차이점: 함수 선언 시 호이스팅(Hoisting)이 일어나지만, 클래스 선언은 그렇지 않음

    • 호이스팅(Hoisting): 자바스크립트 코드는 함수 안의 모든 변수를 함수 맨 꼭대기로 끌어올린 것처럼 동작함, 그 현상을 호이스팅이라고 칭함
  • 따라서, 클래스를 사용하여 객체를 만들기 위해서는 미리 클래스 선언을 해둬야 함 👉🏻 그렇지 않으면, ReferenceError 발생

Class 표현식

  • 클래스를 정의하는 또 다른 방식
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 이름을 갖지 않는 클래스
let Square = class {
  constructor(height, width) {
    this.height = height
    this.width = width
  }
}

console.log(Square.name)
// "Square"

// 이름을 갖는 클래스
let Square = class Triangle {
  constructor(height, width) {
    this.height = height
    this.width = width
  }
}

console.log(Square.name)
// "Triangle"
  • 클래스를 동적 생성 하는 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
function makeClass(name) {
  // 클래스 선언 및 반환
  return class {
    sayHi() {
      alert('Hello, ' + name)
    }
  }
}

// 새로운 클래스를 만듦
let User = makeClass('Kim')

new User().sayHi() // Hello, Kim

생성자와 메소드🔨

Constructor 생성자

  • 클래스로 생성된 객체를 생성 & 초기화하기 위한 특수한 메소드
  • 새로운 클래스 생성 시 가장 처음 실행됨
  • constructor를 사용하여 class 객체의 초기값을 설정할 수 있음
1
2
3
4
5
6
7
8
9
10
class Human {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
}

const kim = new Human('Kim', 15)
console.log(kim)
// Human {name: 'Kim', age: 15}
  • 클래스 내에 한 개만 존재 👉🏻 그렇지 않으면 SyntaxError 발생
  • constructor는 부모 클래스의 생성자를 호출하기 위해 super 키워드 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
class Square {
  constructor(name) {
    this.name = name
  }

  sayHi() {
    alert(this.name)
  }
}

let square = new Square('Nemo')
square.sayHi()
// "Nemo"
  • new Square(“Nemo”) 호출 시
    • 새로운 객체 생성됨
    • 인수와 함께 constructor 자동 실행 👉🏻 인수인 “Nemo” 곧 name이기 때문에 this.name = name 로 인해 this.name에 할당됨
  • 다음과 같은 과정을 거친 뒤, square.sayHi()와 같이 객체 메소드를 호출할 수 있음

Method 메소드

  • constructor로 설정한 초기값을 이용하여 특정 기능을 수행하는 메소드를 만들 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Human {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  changeName(newName) {
    this.name = newName
  }
}

const park = new Human()
park.changeName('Park')
console.log(park.name)
// 'Park'
  • 클래스 밖에서 새로운 메소드를 생성해서 사용할 수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Human {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  changeName(newName) {
    this.name = newName
  }
}

const kim = new Human('Kim', 24)

kim.sayHi = function () {
  return 'Hi, ' + this.name
}

console.log(kim.sayHi())
// "Hi, Kim"
  • 이렇게 외부에서 만들어서 사용하는 메소드는 새로운 객체를 만들었을 때도 사용할 수 있는 것은 아니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Human {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  changeName(newName) {
    this.name = newName
  }
}

const kim = new Human('Kim', 24)

kim.sayHi = function () {
  return 'Hi, ' + this.name
}

console.log(kim.sayHi())

const park = new Human('Park', 13)
console.log(park.sayHi())
// TypeError: park.sayHi is not a function

Class 상속🤱🏻

extends로 상속하기

  • 클래스를 상속하여 기존 클래스의 속성들을 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Human {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  changeName(newName) {
    this.name = newName
  }
}

class Kid extends Human {
  saySchoolName(schoolName) {
    this.schoolName = schoolName
    return `저는 ${this.schoolName}에 다녀요.`
  }
}

const choi = new Kid()
console.log(choi.saySchoolName('oo 초등학교'))
// "저는 oo 초등학교에 다녀요."

super로 가져다 쓰기

  • 상위 클래스(부모 클래스)가 갖고 있는 메소드나 초기값을 가져다 쓸 수 있다.
    • 부모가 가진 초기값을 가져와서 세팅한 뒤, 자식 클래스 내에서만 사용할 초기값을 따로 정의할 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Human {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  changeName(newName) {
    this.name = newName
  }
}

class Kid extends Human {
  constructor(name, age, schoolName) {
    super(name, age) // 부모 클래스의 초기값 가져다 쓰기
    this.schoolName = schoolName
  }

  saySchoolName() {
    return `저는 ${this.schoolName}에 다녀요.`
  }

  sayNewName(newName) {
    super.changeName(newName) // 부모 클래스의 메소드 가져다 쓰기
    return `저의 새 이름은 ${this.name}입니다.`
  }
}

const choi = new Kid('Choi', 10, 'oo 초등학교')
console.log(choi.saySchoolName())
// "저는 oo 초등학교에 다녀요."
console.log(choi.sayNewName('Choi Kim Park'))
// "저의 새 이름은 Choi Kim Park입니다."

참고1

참고2