λͺ¨λ μλ°μ€ν¬λ¦½νΈ Deep Dive λμμ 25μ₯μ μ 리νμμ΅λλ€.
μλ°μ€ν¬λ¦½νΈλ νλ‘ν νμ κΈ°λ° κ°μ²΄μ§ν₯ μΈμ΄λ€. ES6μμ λμ λ ν΄λμ€λ κ°μ²΄μ§ν₯ νλ‘κ·Έλλ° μΈμ΄μ λ§€μ° ν‘μ¬ν μλ‘μ΄ κ°μ²΄ μμ± λ©μ»€λμ¦μ μ μνλ€. μ¬μ€ ν΄λμ€λ ν¨μμ΄λ©° κΈ°μ‘΄ νλ‘ν νμ κΈ°λ° ν¨ν΄μ ν΄λμ€ κΈ°λ° ν¨ν΄μ²λΌ μ¬μ©ν μ μλλ‘ νλ λ¬Έλ²μ μ€ν(λ μ½κ² μ½κ±°λ ννν μ μλλ‘ μ€κ³λ νλ‘κ·Έλλ° μΈμ΄ λ΄μ ꡬ문)μ΄λΌκ³ λ³Ό μλ μλ€.
ν΄λμ€μ μμ±μ ν¨μλ λͺ¨λ νλ‘ν νμ κΈ°λ°μ μΈμ€ν΄μ€λ₯Ό μμ±νμ§λ§ μ νν λμΌνκ² λμνμ§λ μλλ€. ν΄λμ€λ₯Ό λ¨μν λ¬Έλ²μ μ€νμ΄λΌκ³ 보기보λ€λ μλ‘μ΄ κ°μ²΄ μμ± λ©μ»€λμ¦μΌλ‘ 보λ κ²μ΄ μ’ λ ν©λΉνλ€.
class
ν€μλλ₯Ό μ¬μ©νμ¬ μ μνλ€.ν΄λμ€ λͺΈμ²΄μλ 0κ° μ΄μμ λ©μλλ§ μ μν μ μλ€.
class Person {
// μμ±μ
constructor(name) {
this.name = name // name νλ‘νΌν°λ publicνλ€.
}
// νλ‘ν νμ
λ©μλ
sayHi() {
console.log(`Hi! My name is ${this.name}`)
}
// μ μ λ©μλ
static sayHello() {
console.log(`Hello!~`)
}
}
// μΈμ€ν΄μ€ μμ±
const me = new person('Lee')
// μΈμ€ν΄μ€μ νλ‘νΌν° μ°Έμ‘°
console.log(me.name) // Lee
// νλ‘ν νμ
λ©μλ νΈμΆ
me.sayHi() // Hi! My name is Lee
// μ μ λ©μλ νΈμΆ
Person.sayHello() // Hello
ν΄λμ€λ ν¨μλ‘ νκ°λλ€.
class Person {}
console.log(typeof Person) // function
ν΄λμ€ μ μΈλ¬ΈμΌλ‘ μ μν ν΄λμ€λ ν¨μ μ μΈλ¬Έκ³Ό κ°μ΄ μμ€μ½λ νκ° κ³Όμ , μ¦ λ°νμ μ΄μ μ λ¨Όμ νκ°λμ΄ ν¨μ κ°μ²΄λ₯Ό μμ±νλ€. μμ±μ ν¨μλ‘μ νΈμΆν μ μλ ν¨μλ ν¨μ μ μκ° νκ°λμ΄ ν¨μ κ°μ²΄λ₯Ό μμ±νλ μμ μ νλ‘ν νμ λ λλΆμ΄ μμ±λλ€. νλ‘ν νμ κ³Ό μμ±μ ν¨μλ λ¨λ μΌλ‘ μ‘΄μ¬ν μ μκ³ μΈμ λ μμΌλ‘ μ‘΄μ¬νκΈ° λλ¬Έμ΄λ€. λ¨, ν΄λμ€λ ν΄λμ€ μ μ μ΄μ μ μ°Έμ‘°ν μ μλ€.
const Perso = ''
{
console.log(Person) // ReferenceError: Cannot access 'Person' before initialization
// ν΄λμ€ μ μΈλ¬Έ
class Person {}
}
ν΄λμ€λ let, const ν€μλλ‘ μ μΈν λ³μμ²λΌ νΈμ΄μ€ν λλ€. ν΄λμ€ μ μΈλ¬Έ μ΄μ μ TDZμ λΉ μ§κΈ° λλ¬Έμ νΈμ΄μ€ν μ΄ λ°μνμ§ μλ κ²μ²λΌ λμνλ€.
ν΄λμ€λ μμ±μ ν¨μμ΄λ©° new
μ°μ°μμ ν¨κ» νΈμΆλμ΄ μΈμ€ν΄μ€λ₯Ό μμ±νλ€. ν΄λμ€λ new μ°μ°μ μμ΄ νΈμΆνλ©΄ νμ
μλ¬κ° λ°μνλ€.
const Person = class MyClass {}
// ν¨μ ννμκ³Ό λ§μ°¬κ°μ§λ‘ ν΄λμ€λ₯Ό κ°λ¦¬ν€λ μλ³μλ‘ μΈμ€ν΄μ€λ₯Ό μμ±ν΄μΌ νλ€.
const me = new Person()
// ν΄λμ€ μ΄λ¦ MyClassλ ν¨μμ λμΌνκ² ν΄λμ€ λͺΈμ²΄ λ΄λΆμμλ§ μ ν¨ν μλ³μλ€.
console.log(MyClass) // ReferenceError: MyClass is not defined
const you = new MyClass() // ReferenceError: MyClass is not defined
constructor
μ μΈμ€ν΄μ€λ₯Ό μμ±νκ³ μ΄κΈ°ννκΈ° μν νΉμν λ©μλλ€. constructorμ μ΄λ¦μ λ³κ²½ν μ μλ€.
ν΄λμ€λ νκ°λμ΄ ν¨μ κ°μ²΄κ° λλ€. ν¨μμ λμΌνκ² νλ‘ν νμ κ³Ό μ°κ²°λμ΄ μμΌλ©° μμ μ μ€μ½ν체μΈμ ꡬμ±νλ€. λͺ¨λ ν¨μ κ°μ²΄κ° κ°μ§κ³ μλ prototype νλ‘νΌν°κ° κ°λ¦¬ν€λ νλ‘ν νμ κ°μ²΄μ constructor νλ‘νΌν°λ ν΄λμ€ μμ μ κ°λ¦¬ν€κ³ μλ€.
constructor λ΄λΆμ thisλ μμ±μ ν¨μμ λ§μ°¬κ°μ§λ‘ ν΄λμ€κ° μμ±ν μΈμ€ν΄μ€λ₯Ό κ°λ¦¬ν¨λ€.
ν΄λμ€ μ μκ° νκ°λλ©΄ constructorμ κΈ°μ λ λμμ νλ ν¨μ κ°μ²΄κ° μμ±λλ€.
constrouctor νΉμ§
1. ν΄λμ€ λ΄μ μ΅λ ν κ°λ§ μ‘΄μ¬ν μ μλ€.
2. μλ΅ν μ μλ€. -> λΉ constructorκ° μ묡μ μΌλ‘ μ μλλ€.
3. μΈμ€ν΄μ€λ₯Ό μ΄κΈ°ννλ €λ©΄ constructorλ μλ΅νλ©΄ μλλ€.
4. λͺ
μμ μΌλ‘ μμκ°μ λ°ννλ©΄ μμκ° λ°νμ 무μλκ³ μ묡μ μ thisκ° λ°νλλ€.
ν΄λμ€ λͺΈμ²΄μμ μ μν λ©μλλ ν΄λμ€μ prototype νλ‘νΌν°μ λ©μλλ₯Ό μΆκ°νμ§ μγ λλ κΈ°λ³Έμ μΌλ‘ νλ‘ν νμ λ©μλκ° λλ€.
μΈμ€ν΄μ€λ νλ‘ν νμ λ©μλλ₯Ό μμλ°μ μ¬μ©ν μ μλ€.
μ μ λ©μλλ μΈμ€ν΄μ€λ₯Ό μμ±νμ§ μμλ νΈμΆν μ μλ λ©μλλ₯Ό λ§νλ€. ν΄λμ€μμ λ©μλμ static
ν€μλλ₯Ό λΆμ΄λ©΄ μ μ λ©μλκ° λλ€.
ν΄λμ€λ ν¨μ κ°μ²΄λ‘ νκ°λλ―λ‘ μμ μ νλ‘νΌν°/λ©μλλ₯Ό μμ ν μ μλ€. ν΄λμ€λ ν΄λμ€ μ μκ° νκ°λλ μμ μ ν¨μ κ°μ²΄κ° λλ―λ‘ μΈμ€ν΄μ€μ λ¬λ¦¬ λ³λ€λ₯Έ μμ± κ³Όμ μ΄ νμ μλ€. λ°λΌμ μ μ λ©μλλ ν΄λμ€ μ μ μ΄ν μΈμ€ν΄μ€λ₯Ό μμ±νμ§ μμλ νΈμΆν μ μλ€.
Person.sayHi() // Hi
// μΈμ€ν΄μ€ μμ±
const me = new Person('Lee')
me.sayHi() // TypeError: me.sayHi is not a function
class Square {
// μΈμ€ν΄μ€ νλ‘νΌν°λ₯Ό μ°Έμ‘°νμ§ μλλ€.
static area(width, height) {
return width * height
}
}
console.log(Square.area(10, 10)) // 100
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
νλ‘ν νμ κ³Ό μ μ λ©μλ λ΄λΆμ this λ°μΈλ©μ΄ λ€λ₯΄λ€. λ°λΌμ λ©μλ λ΄λΆμμ μΈμ€ν΄μ€ νλ‘νΌν°λ₯Ό μ°Έμ‘°ν΄μΌν νμκ° μλ€λ©΄ thisλ₯Ό νμ©ν΄μΌ νλ©°, μ΄λ° κ²½μ°λ νλ‘ν νμ λ©μλλ‘ μ μν΄μΌ νλ€. νμ§λ§ λ©μλ λ΄λΆμμ μΈμ€ν΄μ€ νλ‘νΌν°λ₯Ό μ°Έμ‘°ν΄μΌ ν νμκ° μλ€λ©΄ thisλ₯Ό μ¬μ©νμ§ μκ² λλ€.
νμ€ λΉνΈμΈ κ°μ²΄μΈ Math, Number, JSON, Object, Reflect
λ±μ λ€μν μ μ λ©μλλ₯Ό κ°μ§κ³ μλ€. μ΄λ€ μ μ λ©μλλ μ ν리μΌμ΄μ
μ μμμ μ¬μ©ν μ νΈλ¦¬ν° ν¨μλ€.
ν΄λμ€ λλ μμ±μ ν¨μλ₯Ό νλμ λ€μμ€νμ΄μ€λ‘ μ¬μ©νμ¬ μ μ λ©μλλ₯Ό λͺ¨μ λμΌλ©΄ μ΄λ¦ μΆ©λ κ°λ₯μ±μ μ€μ¬ μ£Όκ³ κ΄λ ¨ ν¨μλ€μ ꡬ쑰νν μ μλ ν¨κ³Όκ° μλ€.
class Person {
constructor(name) {
// 1. μ묡μ μΌλ‘ μΈμ€ν΄μ€κ° μμ±λκ³ thisμ λ°μΈλ©λλ€.
console.log(this) // Person {}
console.log(Object.getPrototypeOf(this) === Person.prototype) // true
// 2. thisμ λ°μΈλ©λμ΄ μλ μΈμ€ν΄μ€λ₯Ό μ΄κΈ°ννλ€.
this.name = name
// 3. μμ±λ μΈμ€ν΄μ€κ° λ°μΈλ©λ thisκ° μ묡μ μΌλ‘ λ°νλλ€.
}
}
μΈμ€ν΄μ€ νλ‘νΌν°λ constructor λ΄λΆμμ μ μν΄μΌ νλ€. constructor λ΄λΆμμ thisμ μΆκ°ν νλ‘νΌν°λ μΈμ λ ν΄λμ€κ° μμ±ν μΈμ€ν΄μ€μ νλ‘νΌν°κ° λλ€. μΈμ€ν΄μ€ νλ‘νΌν°λ μΈμ λ publicνλ€.
μ체μ μΌλ‘λ κ°([[Value]])μ κ°μ§ μκ³ λ€λ₯Έ λ°μ΄ν° νλ‘νΌν°μ κ°μ μ½κ±°λ μ μ₯ν λ μ¬μ©νλ μ κ·Όμ ν¨μ(getter, setter)λ‘ κ΅¬μ±λ νλ‘νΌν°λ€.
getterμ setterμ μΈμ€ν΄μ€ νλ‘νΌν°μ²λΌ μ¬μ©λλ€. νλ‘νΌν°μ²λΌ μ°Έμ‘°νλ νμμΌλ‘ μ¬μ©νλ©°, μ°Έμ‘° μμ λ΄λΆμ μΌλ‘ getterλ setterκ° νΈμΆλλ€.
ν΄λμ€ νλλ ν΄λμ€ κΈ°λ° κ°μ²΄ μ§ν₯ μΈμ΄μμ ν΄λμ€κ° μμ±ν μΈμ€ν΄μ€μ νλ‘νΌν°λ₯Ό κ°λ¦¬ν€λ μ©μ΄μ΄λ€. μλ°μ€ν¬λ¦½νΈμ ν΄λμ€ λͺΈμ²΄μλ λ©μλλ§ μ μΈν μ μλ€.
class Person {
name = 'Lee'
}
const me = new Person('Lee')
μ μμ λ₯Ό μ΅μ λΈλΌμ°μ (Chrome 72 μ΄μ) λλ μ΅μ Node.js(λ²μ 12 μ΄μ)μμ μ€ννλ©΄ μ μ λμνλ€. νμ§λ§ μμ§ ECMAScriptμ μ μ νμ€ μ¬μμΌλ‘ μΉκΈλμ§ μμλ€. νμ§λ§ μΉκΈμ΄ νμ€μ λλ μ΄ μ μμ μ μ μ μΌλ‘ 미리 ꡬνν΄ λμκΈ° λλ¬Έμ ν΄λμ€ νλλ₯Ό ν΄λμ€ λͺΈμ²΄μ μ μν μ μλ κ²μ΄λ€.
ν΄λμ€ νλμ ν¨μλ₯Ό ν λΉ νλ κ²½μ° μ΄ ν¨μλ μΈμ€ν΄μ€ λ©μλκ° λλ€. λͺ¨λ ν΄λμ€ νλλ μΈμ€ν΄μ€ νλ‘νΌν°κ° λκΈ° λλ¬Έμ΄λ€. ν΄λμ€ νλμ ν¨μλ₯Ό ν λΉνλ κ²μ κΆμ₯νμ§ μλλ€.
TC39 νλ‘μΈμ€μ stage3μλ private νλλ₯Ό μ μν μ μλ μλ‘μ΄ νμ€ μ¬μμ΄ μ μλμ΄ μλ€. μ΄ μ μλ μ΅μ λΆλΌμ°μ μ μ΅μ Node.jsμ μ΄λ―Έ ꡬνλμ΄ μλ€. private νλμ μ λμλ #μ λΆμ¬μ€λ€.
class Person {
#name = ''
constructor(name) {
// private νλ μ°Έμ‘°
this.#name = name
}
}
λ€λ§ private νλλ λ°λμ ν΄λμ€ λͺΈμ²΄μ μ μν΄μΌ νλ€.
static ν€μλλ₯Ό μ¬μ©νμ¬ μ μ νλλ₯Ό μ μν μ μλλ‘ TC39 νλ‘μΈμ€μ stage3μ μ μλμ΄ μλ€.
class MyMath {
// static public νλ μ μ
static PI = 22 / 7
// static private νλ μ μ
static #num = 10
// static λ©μλ
static increment() {
return ++MyMath.#num
}
}
console.log(MyMath.PI) // 3.142858---
console.log(MyMath.increment()) // 11
κΈ°μ‘΄ ν΄λμ€λ₯Ό μμλ°μ μλ‘μ΄ ν΄λμ€λ₯Ό νμ₯νμ¬ μ μνλ κ²μ΄λ€.
ν΄λμ€λ μμμ ν΅ν΄ λ€λ₯Έ ν΄λμ€λ₯Ό νμ₯ν μ μλ λ¬Έλ²μΈ extends
ν€μλκ° κΈ°λ³Έμ μΌλ‘ μ 곡λλ€. νμ§λ§ μμ±μ ν¨μλ ν΄λμ€μ κ°μ΄ μμμ ν΅ν΄ λ€λ₯Έ μμ±μ ν¨μλ₯Ό νμ₯ν μ μλ λ¬Έλ²μ΄ μ 곡λμ§ μλλ€. μμ¬ ν΄λμ€ μμ ν¨ν΄μ μ΄μ©νμ¬ νλ΄λΌ μλ μλ€.
// μνΌ/λΆλͺ¨ ν΄λμ€
class Base {}
// μλΈ/μμ ν΄λμ€
class Derived extends Base {}
extends ν€μλ λ€μμλ ν΄λμ€ λΏλ§ μλλΌ [[Construct]] λ΄λΆ λ©μλλ₯Ό κ°λ ν¨μ κ°μ²΄λ‘ νκ°λ μ μλ λͺ¨λ ννμμ μ¬μ©ν μ μλ€.
function Base1() {}
class Base2 {}
let condition = true
class Derived extends (condition ? Base1 : Base2) {}
μλΈ ν΄λμ€μμ constructor μλ΅νλ©΄ λ€μκ³Ό κ°μ constructor μ묡μ μΌλ‘ μ μλλ€. argsλ new μ°μ°μμ ν¨κ» ν΄λμ€λ₯Ό νΈμΆν λ μ λ¬ν μΈμ 리μ€νΈλ€.
super()λ μνΌν΄λμ€μ constructorλ₯Ό νΈμΆνμ¬ μΈμ€ν΄μ€λ₯Ό μμ±νλ€.
class Base {
constructor() {}
}
class Derived extends Base {
// λ€μκ³Ό κ°μ΄ μ묡μ μΌλ‘ constructorκ° μ μλλ€.
constructor(...args) {
super(...args)
}
}
const derived = new Derived()
console.log(derived) // Derived {}
super ν€μλλ ν¨μμ²λΌ νΈμΆν μλ μκ³ thisμ κ°μ΄ μλ³μμ²λΌ μ°Έμ‘°ν μ μλ€.
superλ₯Ό νΈμΆνλ©΄ μνΌν΄λμ€μ constructorλ₯Ό νΈμΆνλ€.
λ€μ μμ μΈ κ°μ΄ μνΌν΄λμ€μμ μΆκ°ν νλ‘νΌν°μ μλΈν΄λμ€μμ μΆκ°ν νλ‘νΌν°λ₯Ό κ°λ μΈμ€ν΄μ€λ₯Ό μμ±νλ€λ©΄ μλΈν΄λμ€μ constructorλ₯Ό μλ΅ν μ μλ€.
class Base {
constructor(a, b) { // 2) 1μμ νΈμΆν μΈμλ₯Ό μ λ¬ λ°μ
this.a = a
this.b = b
}
}
class Derived extends Base {
constructor(a, b, c) {
super(a, b) // 1) superνΈμΆλ‘ Base ν΄λμ€λ‘ 보λ
this.c = c
}
}
const derived = new Derived(1, 2, 3)
console.log(derived) // Derived {a: 1, b:2, c: 3}
super νΈμΆ μ μ£Όμμ¬ν
1. μλΈν΄λμ€μμ constructorλ₯Ό μλ΅νμ§ μλ κ²½μ° μλΈν΄λμ€μ constructorμμλ λ°λμ superλ₯Ό νΈμΆν΄μΌ νλ€.
class Base {}
class Derived extends Base {
constructor() {
// ReferenceError
}
}
class Base {}
class Derived extends Base {
constructor() {
// ReferenceError
this.a = 1
super()
}
}
superμ μ°Έμ‘°νλ©΄ μνΌν΄λμ€μ λ©μλλ₯Ό νΈμΆν μ μλ€.
μλΈν΄λμ€μ νλ‘ν ν°μ λ©μλ λ΄μμ super.sayHiλ μνΌν΄λμ€μ νλ‘ν°νμ λ©μλ sayHiλ₯Ό κ°λ¦¬ν¨λ€.
μλΈν΄λμ€μ μ μ λ©μλ λ΄μμ super.sayHiλ μνΌν΄λμ€μ μ μ λ©μλ sayHiλ₯Ό κ°λ¦¬ν¨λ€.
μλ°μ€ν¬λ¦½νΈ μμ§μ ν΄λμ€λ₯Ό νκ°ν λ μνΌν΄λμ€μ μλΈν΄λμ€λ₯Ό ꡬλΆνκΈ° μν΄ 'base' λλ 'derived'λ₯Ό κ°μΌλ‘ κ°λ λ΄λΆ μ¬λ‘― [[ConstructorKind]]λ₯Ό κ°λλ€.
μλΈν΄λμ€λ μμ μ΄ μ§μ μΈμ€ν΄μ€λ₯Ό μμ±νμ§ μκ³ μνΌν΄λμ€μκ² μΈμ€ν΄μ€ μμ±μ μμνλ€. μ΄κ²μ΄ λ°λ‘ μλΈν΄λμ€μ constructorμμ superμ νΈμΆν΄μΌ νλ μ΄μ λ€.
μνΌν΄λμ€μ consturctor λ΄λΆμ μ½λκ° μ€νλκΈ° μ΄μ μ μ묡μ μΌλ‘ λΉ κ°μ²΄λ₯Ό μμ±νλ€. μ΄ λΉ κ°μ²΄κ° λ°λ‘ ν΄λμ€κ° μμ±ν μΈμ€ν΄μ€μ΄λ€. μ΄λ μΈμ€ν΄μ€λ μνΌν΄λμ€κ° μμ±ν κ²μ΄λ€. νμ§λ§ new μ°μ°μμ ν¨κ» νΈμΆλ ν΄λμ€κ° μλΈν΄λμ€ λΌλ κ²μ΄ μ€μνλ€. μΈμ€ν΄μ€λ new.targetμ΄ κ°λ¦¬ν€λ μλΈν΄λμ€κ° μμ±ν κ²μΌλ‘ μ²λ¦¬
λλ€.
μνΌν΄λμ€μ constructorκ° μ€νλμ΄ thisμ λ°μΈλ©λμ΄ μλ μΈμ€ν΄μ€λ₯Ό μ΄κΈ°ννλ€.
super νΈμΆμ΄ μ’ λ£λκ³ μ μ΄ νλ¦μ΄ μλΈν΄λμ€ constructorλ‘ λμμ¨λ€. μ΄λ superμ΄ λ°νν μΈμ€ν΄μ€κ° thisμ λ°μΈλ©λλ€.
super νΈμΆ μ΄ν, μλΈν΄λμ€μ constructorμ κΈ°μ λμ΄ μλ μΈμ€ν΄μ€ μ΄κΈ°νκ° μ€νλλ€.
ν΄λμ€μ λͺ¨λ μ²λ¦¬κ° λλλ©΄ μμ±λ μΈμ€ν΄μ€κ° λ°μΈλ©λ thisκ° μ묡μ μΌλ‘ λ°νλλ€.
Ref
- μ΄μ λͺ¨ μ , βλͺ¨λ μλ°μ€ν¬λ¦½νΈ Deep Diveβ, μν€λΆμ€