ํด๋ž˜์Šค

@choi2021 ยท December 23, 2022 ยท 17 min read

๐Ÿ‘“ Class

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ž์ฒด๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ์ฒด์ง€ํ–ฅ์„ ์ง€์›ํ•˜๋Š” ์–ธ์–ด๋‹ค. ํด๋ž˜์Šค๋Š” ํด๋ž˜์Šค์— ์ต์ˆ™ํ•œ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•œ ํ”„๋กœํ† ํƒ€์ž…์˜ ๋ฌธ๋ฒ•์  ์„คํƒ•์ด๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค. ํ•˜์ง€๋งŒ ํด๋ž˜์Šค๊ฐ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋‚ด์—์„œ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์— ์ฐจ์ด์ ์ด ์กด์žฌํ•œ๋‹ค. ํด๋ž˜์Šค์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž

๐Ÿ™„ ํด๋ž˜์Šค์˜ ์ •์ฒด์™€ ํ˜ธ์ด์ŠคํŒ…

๋จผ์ € ํด๋ž˜์Šค๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•จ์ˆ˜๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•จ์ˆ˜๋Š” ์ผ๊ธ‰๊ฐ์ฒด์ด๋ฏ€๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜, ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ๋ณ€์ˆ˜์— ์ €์žฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ๊ฐ™์ด ํ•จ์ˆ˜์ง€๋งŒ ์ฐจ์ด์ ์ด ์กด์žฌํ•œ๋‹ค. ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” new๊ฐ€ ์—†์ด ํ˜ธ์ถœ ์‹œ์— ํ•จ์ˆ˜๋กœ์จ ๋™์ž‘ํ•˜์ง€๋งŒ, ํด๋ž˜์Šค๋Š” new ํ‚ค์›Œ๋“œ์—†์ด ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค.

class Cat {
  constructor() {
    this.name = "์•ผ์˜น์ด"
  }
  call() {
    console.log(this.name)
  }
}

console.log(Cat()) //TypeError: Class constructor Cat cannot be invoked without 'new'

์œ„ ์ฝ”๋“œ์—์„œ new์—†์ด ํ˜ธ์ถœ์‹œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํด๋ž˜์Šค๋Š” ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํ˜ธ์ด์ŠคํŒ…์ด ๋ฐœ์ƒํ•˜์ง€๋งŒ, const, let์œผ๋กœ ํ•จ์ˆ˜ํ‘œํ˜„์‹๊ณผ ๊ฐ™์ด ์ดˆ๊ธฐํ™” ์ „๊นŒ์ง€ ํ˜ธ์ถœ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ TDZ์— ๋น ์ง€๋Š” ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

const Cat = ""
{
  console.log(Cat) // ReferenceError: Cannot access 'Cat' before initialization
  class Cat {}
}

์œ„ ์ฝ”๋“œ์—์„œ ํ˜ธ์ด์ŠคํŒ…๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์ „์—ญ์—์„œ ๋งŒ๋“  Cat ๋ณ€์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— " "๋กœ ์ฝ˜์†”์— ๋‚˜์™€์•ผํ•œ๋‹ค. ํ•˜์ง€๋งŒ ํ˜ธ์ด์ŠคํŒ…์ด ์ผ์–ด๋‚˜ ์—๋Ÿฌ๊ฐ€ ๋‚œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ˜Ž ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ

ํด๋ž˜์Šค๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ๊ฐ™์ด ์ธ์Šคํ„ด์Šค ๋ฉ”์†Œ๋“œ, ์ •์  ๋ฉ”์†Œ๋“œ, ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์†Œ๋“œ, ์ด ์„ธ๊ฐ€์ง€ ๋ฉ”์†Œ๋“œ ์˜์—ญ์„ ๊ฐ€์ง„๋‹ค. ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

constructor

constructor ๋ฉ”์†Œ๋“œ๋Š” class๋กœ ๋งŒ๋“ค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ๋‹ค. ํด๋ž˜์Šค๋Š” ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€์ง€๋Š”๋ฐ ์ด๋•Œ ํ”„๋กœํ† ํƒ€์ž…์˜ constructor๋Š” ํด๋ž˜์Šค ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค.

constructor
constructor
๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค ์ž์ฒด๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ , constructor ๋‚ด๋ถ€์˜ this๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌ์ผœ ๋งŒ๋“ค์–ด์งˆ ์ธ์Šคํ„ด์Šค์˜ ์ดˆ๊ธฐ๊ฐ’์„ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ constructor๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์—์„œ ์•”๋ฌต์ ์œผ๋กœ return this๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ณ  ์žˆ๋‹ค. ์ƒ์„ฑ์žํ•จ์ˆ˜์—์„œ this๋กœ ์ธ์Šคํ„ด์Šค์˜ ์†์„ฑ์„ ์ •ํ•ด์ฃผ๋˜ ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค.

์ด๋•Œ this๋Œ€์‹  ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ returnํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง€๊ธฐ ๋•Œ๋ฌธ์— return์„ ์ƒ๋žตํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค.

class Cat {
  constructor(name) {
    this.name = name
    return {}
  }
}

const cat = new Cat("์–‘์˜น")
console.log(cat) // {}

ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด์ง„ ์ธ์Šคํ„ด์Šค๋„ ์ƒ์„ฑ์žํ•จ์ˆ˜๊ฐ€ ๋งŒ๋“  ์ธ์Šคํ„ด์Šค์™€ ๋™์ผํ•˜๊ฒŒ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค. ๊ฒฐ๊ตญ ์ •๋ฆฌํ•˜๋ฉด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์—์„œ ํด๋ž˜์Šค๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

class
class

ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์†Œ๋“œ

์ƒ์„ฑ์žํ•จ์ˆ˜์—์„œ๋Š” ์ธ์Šคํ„ด์Šค๋“ค์ด ๊ณตํ†ต์œผ๋กœ ์ฐธ์กฐํ•  ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ๋•Œ, ํ”„๋กœํ† ํƒ€์ž…์— ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ–ˆ์ง€๋งŒ ํด๋ž˜์Šค์—์„œ๋Š” ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธํ•˜๋ฉด ์ž๋™์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž…์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋œ๋‹ค.

class Cat {
  constructor(name) {
    this.name = name // ์ธ์Šคํ„ด์Šค ๋ฉ”์†Œ๋“œ
  }
  call() {
    //ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์†Œ๋“œ
    console.log("์•ผ์˜น")
  }
}

const cat = new Cat("์•ผ์˜น์ด")
cat.call() // ์•ผ์˜น
cat.__proto__.call("์•ผ์˜น")

์ •์  ๋ฉ”์†Œ๋“œ

์ •์  ๋ฉ”์†Œ๋“œ๋Š” ์ƒ์„ฑ์žํ•จ์ˆ˜์—์„œ ์ƒ์„ฑ์žํ•จ์ˆ˜๊ฐ์ฒด ์ž์ฒด๊ฐ€ ๊ฐ–๋Š” ์†์„ฑ์œผ๋กœ, ํด๋ž˜์Šค์—์„œ๋Š” static์„ ๋ถ™์—ฌ ์ •์  ๋ฉ”์†Œ๋“œ๋ฅผ ์ •ํ•œ๋‹ค. class ์ž์ฒด๊ฐ€ ๊ฐ–๋Š” ๋ฉ”์†Œ๋“œ๋กœ ์ ˆ๋Œ“๊ฐ’์ด๋‚˜ ๋žœ๋คํ•œ ์ˆ˜๋ฅผ ์–ป์„ ๋•Œ ์‚ฌ์šฉํ•˜๋˜ Math.abs()๊ฐ€ static ํ•จ์ˆ˜์˜ ์˜ˆ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ์ •์  ๋ฉ”์†Œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค์—๊ฒŒ ์ƒ์†๋˜์ง€ ์•Š๋Š” ๋ฉ”์†Œ๋“œ๋กœ ๋ณ„๋„์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•ด์„œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

class Cat {
  static shout = () => console.log("์•ผ์˜น") // ์ •์  ๋ฉ”์†Œ๋“œ
}

Cat.shout() //์•ผ์šฉ

๐Ÿฅš ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ๊ณผ์ •

ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •์„ ์ •๋ฆฌํ•˜๋ฉด ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ๊ฐ€์žฅ ๋จผ์ € new ํ‚ค์›Œ๋“œ๋กœ ๋นˆ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  this๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. constructor ๋‚ด๋ถ€์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐํ™”ํ•œ ํ›„์— ์ƒ๋žต๋œ return this๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ ๋‹ค. ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์†Œ๋“œ๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ํ†ตํ•ด ์ƒ์†๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž์ฒด์ ์œผ๋กœ๋Š” ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค.

class Cat {
  static shout = () => console.log("์•ผ์˜น")

  constructor(name) {
    this.name = name
  }
  call() {
    console.log("ํ•˜์ด")
  }
}

const cat = new Cat("์•ผ์˜น")

console.log(cat.hasOwnProperty("call")) //false
console.log(cat.__proto__.hasOwnProperty("call")) //true

๐Ÿฉธ ํด๋ž˜์Šค์˜ getter์™€ setter

ํด๋ž˜์Šค๋Š” getter์™€ setter๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ ์†์„ฑ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. getter์™€ setter๋Š” ๋ชจ๋‘ ํ•จ์ˆ˜์ง€๋งŒ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋‹ค๋ฅธ ์†์„ฑ๊ณผ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•œ๋‹ค. getter๋Š” ํ•ด๋‹น ์†์„ฑ์— ์ ‘๊ทผํ•  ๋•Œ ์ˆ˜ํ–‰๋˜๋Š” ํ•จ์ˆ˜์ด๋ฉฐ ํ•ญ์ƒ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ค˜์•ผ ํ•˜๊ณ , setter๋Š” ํ•ด๋‹น ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ๋•Œ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜์ด๋ฏ€๋กœ ํ•ญ์ƒ ์ธ์ž๊ฐ€ ํ•„์š”ํ•˜๋‹ค. getter์™€ setter๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
  fullName() {
    return `${this.firstName} ${this.lastName}`
  }
}

const person1 = new Person(100, 90)
console.log(person1.averageScore()) //ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์•ผํ•ด

์œ„์˜ ์ฝ”๋“œ์˜ ์ ์ˆ˜์˜ ํ‰๊ท  ๊ฐ’์„ ์–ป๊ณ  ์‹ถ์€ ์ƒํ™ฉ์—์„œ ๋ฉ”์†Œ๋“œ๋กœ ํ‰๊ท  ์ ์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ์ง€๋งŒ averageScore๋ฅผ ์†์„ฑ์œผ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ์„ ์€ ์ดˆ๊ธฐ ๊ฐ’์œผ๋กœ ๋จผ์ € ๋ฐ›์•„์˜ฌ ๋•Œ ๊ณ„์‚ฐํ•ด์„œ ์†์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
    this.fullName = `${this.firstName} ${this.lastName}`
  }
}

const me = new Person("Youngjun", "Choi")
console.log(me.fullName) // Youngjun Choi
me.firstName = "hi"
console.log(me.fullName) // Youngjun Choi

ํ•˜์ง€๋งŒ ๋ฌธ์ œ์ ์€ ์ดˆ๊ธฐํ™”๋กœ ๊ฐ’์ด ์ •ํ•ด์ ธ๋ฒ„๋ ค ์ˆ˜ํ•™ ์ ์ˆ˜๋ฅผ ์ˆ˜์ •ํ–ˆ์„ ๋•Œ ํ‰๊ท ๊ฐ’์€ ๋ฐ˜์˜์ด ์•ˆ๋˜๊ณ  ์žˆ๋‹ค. ์ด๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด Getter์™€ Setter๋‹ค.

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
  get fullName() {
    return `${this.firstName} ${this.lastName}`
  }

  set fullName(value) {
    this.fullName = value
  }
}

const me = new Person("Youngjun", "Choi")
console.log(me.fullName)
me.fullName = "yj Choi" // RangeError: Maximum call stack size exceeded

getter์™€ setter๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ ์†์„ฑ์— ์ ‘๊ทผํ•ด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ฌ์šฉ ์‹œ์—๋Š” ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋•Œ ์ฃผ์˜ํ•  ์ ์€ setter๊ฐ€ ๋ณ€๊ฒฝํ•˜๋Š” ์†์„ฑ์˜ ์ด๋ฆ„๊ณผ ์ ‘๊ทผํ•˜๋Š” ์†์„ฑ์˜ ์ด๋ฆ„์ด ๊ฐ™์„ ๊ฒฝ์šฐ ๊ณ„์†ํ•ด์„œ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•ด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ’์„ setter ์†์„ฑ์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‚ด๋ถ€ ์†์„ฑ์„ ์ด์šฉํ•ด์„œ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค.

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
  get fullName() {
    return `${this.firstName} ${this.lastName}`
  }

  set fullName(name) {
    ;[this.firstName, this.lastName] = name.split(" ")
  }
}

const me = new Person("Youngjun", "Choi")
console.log(me.fullName) // Youngjun Choi
me.fullName = "yj Choi"
console.log(me.fullName) // yj Choi

getter์™€ setter๋Š” ํด๋ž˜์Šค ๋ ˆ๋ฒจ์˜ ์ ‘๊ทผ์ž์ด๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํ† ํƒ€์ž…์˜ ์†์„ฑ์ด ๋œ๋‹ค.

class3
class3

๐Ÿ—บ ํด๋ž˜์Šค์˜ ํ•„๋“œ

ํด๋ž˜์Šค์˜ ํ•„๋“œ์— constructor ํ•จ์ˆ˜๋กœ ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ์ธ์Šคํ„ด์Šค ์†์„ฑ์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ this๋Š” ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋˜๊ณ  ์ดˆ๊ธฐ ๊ฐ’์ด ์—†๋‹ค๋ฉด undefined๋กœ ํ• ๋‹น๋œ๋‹ค. ์ธ์Šคํ„ด์Šค ์†์„ฑ์€ ํ•ญ์ƒ public์ด์ง€๋งŒ ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” #์œผ๋กœ private ํ•„๋“œ, ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ๋งŒ ์ฐธ์กฐ ๊ฐ€๋Šฅํ•œ ์†์„ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

class Person {
  #name = "๋น„๋ฐ€"
  get name() {
    return this.#name
  }
}

const me = new Person()

console.log(me.name)
console.log(me.#name) // SyntaxError: Private field '#name' must be declared in an enclosing class

ํด๋ž˜์Šค ํ•„๋“œ์— static์„ ์ด์šฉํ•˜๋ฉด ์•ž์„œ ํด๋ž˜์Šค ๋ ˆ๋ฒจ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“  ๊ฒƒ์ฒ˜๋Ÿผ ์†์„ฑ๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

class Person {
  #name = "๋น„๋ฐ€"
  static male = "๋‚จ์ž"
  get name() {
    return this.#name
  }
}

const me = new Person()
console.log(Person.male) // ๋‚จ์ž

๐Ÿ” ํด๋ž˜์Šค์˜ ์ƒ์†

ํ”„๋กœํ†  ํƒ€์ž…์„ ์ •๋ฆฌํ•˜๋ฉด์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ”„๋กœํ†  ํƒ€์ž…์„ ์ด์šฉํ•ด ์ƒ์†์„ ์ง€์›ํ•œ๋‹ค๊ณ  ํ–ˆ์—ˆ๋‹ค. ํด๋ž˜์Šค๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ณด๋‹ค ํŽธํ•˜๊ฒŒ extendsํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด ์ƒ์†์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ถ€๋ชจ์˜ ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์†์„ ๋ฐ›์•„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ superํ‚ค์›Œ๋“œ ์— ๋Œ€ํ•ด ๋จผ์ € ์•Œ์•„๋ณด์ž

Super

super๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ constructor๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜, ๋ถ€๋ชจ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐธ์กฐํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฐ๊ฐ์˜ ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

๋จผ์ € super๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋Š” ์ค‘์š”ํ•œ ์„ธ ๊ฐ€์ง€ ๊ทœ์น™์ด ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ทœ์น™์€ ์ž์‹ ํด๋ž˜์Šค๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ๋จผ์ € ๋ถ€๋ชจ ํด๋ž˜์Šค์—๊ฒŒ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์„ ์œ„์ž„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ง€์ผœ์ ธ์•ผ ํ•œ๋‹ค.

  1. ์ž์‹ ํด๋ž˜์Šค์—์„œ constructor๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฐ˜๋“œ์‹œ super๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
class Parent {}

class Child extends Parent {
  //ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
  constructor() {}
}

const child = new Child()
  1. ์ž์‹ ํด๋ž˜์Šค์˜ constructor์—์„œ super๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— this๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค.
class Parent {}

class Child extends Parent {
  constructor() {
    //ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
    this.a = 1
    super()
  }
}

const child = new Child()
  1. ์ž์‹์˜ constructor ํ•จ์ˆ˜์—์„œ๋งŒ super๊ฐ€ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ๋‹ค.
class Parent {}

class Child extends Parent {
  constructor() {
    this.a = 1
    super()
  }

  foo() {
    super() // SyntaxError: 'super' keyword unexpected here
  }
}

const child = new Child()

๋‘ ๋ฒˆ์งธ๋กœ super๋ฅผ ์ด์šฉํ•ด ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

class Parent {
  constructor(name) {
    this.name = name
  }

  sayHi() {
    return `${this.name}`
  }
}

class Child extends Parent {
  sayHi() {
    return `${super.sayHi()}` //parent.sayHi()
  }
}

const child = new Child("yj")
console.log(child.sayHi())

์œ„ ์˜ˆ์ œ๋Š” super๋ฅผ ํ†ตํ•ด Parent ํด๋ž˜์Šค์˜ ํ”„๋กœํ† ํƒ€์ž…์˜ sayHi๋ฅผ ์ฐธ์กฐํ–ˆ๋‹ค. ์ด๋•Œ this๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— name์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ super๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‚ด๋ถ€ ์Šฌ๋กฏ [[HomeObject]]๋ฅผ ๊ฐ€์ ธ, ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค. sayHi()๋ฉ”์†Œ๋“œ์˜ [[HomeObject]]์—๋Š” Child.prototype์ด ๋ฐ”์ธ๋”ฉ๋˜๊ณ  super๋ฅผ ์ฐธ์กฐํ•ด child.prototype์˜ ํ”„๋กœํ† ํƒ€์ž…์ธ Parent.prototype์„ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

super๋ฅผ ์ž์‹ ํด๋ž˜์Šค์˜ ์ •์  ๋ฉ”์†Œ๋“œ์—์„œ ์ด์šฉํ•˜๋ฉด ๋ถ€๋ชจ์˜ ์ •์ ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

class Parent {
  static sayHi() {
    return `Hi `
  }
}

class Child extends Parent {
  static sayHi() {
    return `${super.sayHi()}`
  }
}

console.log(Child.sayHi()) // hi

์ด์ œ ์‹ค์ œ๋กœ ์ƒ์†์„ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๊ณผ์ •์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

class Circle {
  constructor(radius) {
    this.radius = radius // ๋ฐ˜์ง€๋ฆ„
  }

  getPerimeter() {
    return 2 * Math.PI * this.radius
  }

  getArea() {
    return Math.PI * this.radius ** 2
  }
}

// ์ž์‹ ํด๋ž˜์Šค
class Cylinder extends Circle {
  constructor(radius, height) {
    super(radius)
    this.height = height
  }

  getArea() {
    return this.height * super.getPerimeter() + 2 * super.getArea()
  }

  getVolume() {
    return super.getArea() * this.height
  }
}

const cylinder = new Cylinder(2, 10)

console.log(cylinder.getPerimeter())

console.log(cylinder.getArea()) // 150.79644737231007

console.log(cylinder.getVolume()) // 125.66370614359172

์œ„์˜ ์˜ˆ์ œ๋กœ ์ธ์Šคํ„ด์Šค cylinder๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ณผ์ •์„ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. Cylinder ํด๋ž˜์Šค์˜ super ํ˜ธ์ถœ

    ๋จผ์ € Cylinder ํด๋ž˜์Šค์˜ constructor๊ฐ€ ํ˜ธ์ถœ๋˜๋Š”๋ฐ ์ด๋•Œ super๋ฅผ ํ†ตํ•ด Cylinder ํด๋ž˜์Šค์—์„œ Circleํด๋ž˜์Šค๋กœ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์ด ์œ„์ž„๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์‹ค์ œ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ณณ์€ Circle ํด๋ž˜์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ์•ž์„œ super๋ฅผ ๋จผ์ € ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

  2. Circle ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ๊ณผ this ๋ฐ”์ธ๋”ฉ

superํ˜ธ์ถœ๋กœ Circleํด๋ž˜์Šค๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € {}๋นˆ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  this๋ฅผ ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. ์ด๋•Œ this๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํ† ํƒ€์ž…์€ Circle.prototype์ด ์•„๋‹ˆ๋ผ Cylinder.prootype์ด ๋œ๋‹ค.

  1. Circle ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™”

    Circleํด๋ž˜์Šค์˜ constructorํ•จ์ˆ˜๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ ํ›„์— Cylinderํด๋ž˜์Šค๋กœ ๋‹ค์‹œ ์ „๋‹ฌํ•œ๋‹ค.

  2. Cylinder ํด๋ž˜์Šค์˜ this๋ฐ”์ธ๋”ฉ

    Cylinderํด๋ž˜์Šค์—์„œ๋Š” ๋ณ„๋„์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ „๋‹ฌ๋ฐ›์€ ์ธ์Šคํ„ด์Šค๋ฅผ this์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— super๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ด์ „์— this๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค.

  3. Cylinder ํด๋ž˜์Šค์˜ ์ดˆ๊ธฐํ™”

    Cylinder ํด๋ž˜์Šค์˜ constructorํ•จ์ˆ˜๋กœ ์ธ์Šคํ„ด์Šค์˜ ์ดˆ๊ธฐํ™”๋ฅผ ์ง„ํ–‰ํ•œ ํ›„์— this๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

์ด๋Ÿฌํ•œ ๊ณผ์ •์„ ํ†ตํ•ด ๋งŒ๋“ค์–ด ์ง„ ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์€ ๋‹ค์Œ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ํ‘œํ˜„๋œ๋‹ค.

class
class

์ด๋•Œ getArea ๋ฉ”์†Œ๋“œ๋Š” ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์—์„œ Cylinder ํด๋ž˜์Šค์— ์˜ํ•ด override๋˜๋ฉด์„œ Circle.prototype ์˜ getArea๊ฐ€ ์•„๋‹Œ Cylinder.prototype์˜ getArea๋กœ ํ˜ธ์ถœ๋˜์–ด ๊ฒฐ๊ณผ๊ฐ€ 4ฯ€๊ฐ€ ์•„๋‹ˆ๋ผ 48ฯ€์— ํ•ด๋‹นํ•˜๋Š” 150.79644737231007๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค.

๋งˆ์น˜๋ฉฐ

์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ํ”„๋กœํ† ํƒ€์ž…์„ ์ดํ•ดํ•˜๊ณ  ํด๋ž˜์Šค๋ฅผ ๋‹ค์‹œ ๋ณด๋ฉด์„œ ๊ณตํ†ต์ ๊ณผ ์ฐจ์ด์ ์„ ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์ดํ›„์— ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ์ข€ ๋” ๊ฐ•๋ ฅํ•œ ๊ฐ์ฒด ์ง€ํ–ฅ ์š”์†Œ๋“ค์„ ํ•จ๊ป˜ ์ •๋ฆฌํ•  ์˜ˆ์ •์ด๋‹ค.

[์ฐธ์กฐ]

@choi2021
๋งค์ผ์˜ ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๊ฐœ๋ฐœ์ผ์ง€์ž…๋‹ˆ๋‹ค.