Understanding Classes in JavaScript - Lee-hyuna/33-js-concepts-kr GitHub Wiki

μ†Œκ°œ

JavaScriptλŠ” ν”„λ‘œν† νƒ€μž… 기반 언어이며, JavaScript의 λͺ¨λ“  κ°μ²΄μ—λŠ” [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)μ΄λΌλŠ” μˆ¨κ²¨μ§„ λ‚΄λΆ€ 속성이 μžˆμ–΄ 객체 νŠΉμ„± 및 λ©”μ„œλ“œλ₯Ό ν™•μž₯ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ΅œκ·ΌκΉŒμ§€λ„ κ°œλ°œμžλ“€μ€ JavaScriptμ—μ„œ 객체 지ν–₯ 섀계 νŒ¨ν„΄μ„ λͺ¨λ°©ν•˜κΈ° μœ„ν•΄ constructor function을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€. ECMAScript 2015 μ–Έμ–΄ 사양은 μ’…μ’… ES6으둜 뢈리며 JavaScript 언어에 클래슀λ₯Ό λ„μž…ν–ˆμŠ΅λ‹ˆλ‹€. JavaScript의 ν΄λž˜μŠ€λŠ” μ‹€μ œλ‘œ μΆ”κ°€ κΈ°λŠ₯을 μ œκ³΅ν•˜μ§€ μ•ŠμœΌλ©°, 더 κΉ¨λ—ν•˜κ³  κ°„κ²°ν•œ 문법을 μ œκ³΅ν•œλ‹€λŠ” μ μ—μ„œ ν”„λ‘œν† νƒ€μž…κ³Ό 상속에 λŒ€ν•΄ "syntactical sugar"λ₯Ό μ œκ³΅ν•˜λŠ” κ²ƒμœΌλ‘œ μ„€λͺ…λ˜κΈ°λ„ ν•©λ‹ˆλ‹€. λ‹€λ₯Έ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œλŠ” 클래슀λ₯Ό μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— JavaScript의 클래슀 ꡬ문을 μ‚¬μš©ν•˜λ©΄ κ°œλ°œμžκ°€ μ–Έμ–΄ 간에 μ‰½κ²Œ 이동할 수 μžˆμŠ΅λ‹ˆλ‹€.

Classes Are Functions

JavaScript ν΄λž˜μŠ€λŠ” ν•¨μˆ˜ μœ ν˜•μž…λ‹ˆλ‹€. ν΄λž˜μŠ€λŠ” class ν‚€μ›Œλ“œλ‘œ μ„ μ–Έλ©λ‹ˆλ‹€. ν•¨μˆ˜ 식 ꡬ문을 μ‚¬μš©ν•˜μ—¬ ν•¨μˆ˜λ₯Ό μ΄ˆκΈ°ν™”ν•˜κ³  클래슀 식 ꡬ문을 μ‚¬μš©ν•˜μ—¬ 클래슀λ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

// Initializing a function with a function expression
const x = function() {}

// Initializing a class with a class expression
const y = class {}

Object.getPrototypeOf() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 객체의 [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)에 μ•‘μ„ΈμŠ€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이걸 μ‚¬μš©ν•˜μ—¬ 빈 function을 μƒμ„±ν•˜λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

Object.getPrototypeOf(x);

// Output
Ζ’ () { [native code] }

classλ₯Ό μƒμ„±ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Object.getPrototypeOf(y);

// Output
Ζ’ () { [native code] }

ν•¨μˆ˜ 및 클래슀둜 μ„ μ–Έλœ μ½”λ“œλŠ” ν•¨μˆ˜ [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)을 λ°˜ν™˜ν•©λ‹ˆλ‹€. ν”„λ‘œν† νƒ€μž…μ„ μ‚¬μš©ν•˜λ©΄ λͺ¨λ“  κΈ°λŠ₯이 μƒˆλ‘œμš΄ ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μƒμ„±μž μΈμŠ€ν„΄μŠ€κ°€ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

const x = function() {}

// Initialize a constructor from a function
const constructorFromFunction = new x();

console.log(constructorFromFunction);

// Output
x {}
constructor: Ζ’ ()

classes도 μ μš©λ©λ‹ˆλ‹€.

const y = class {}

// Initialize a constructor from a class
const constructorFromClass = new y();

console.log(constructorFromClass);
// Output
y {}
constructor: class

μ΄λŸ¬ν•œ ν”„λ‘œν† νƒ€μž… Constructor μ˜ˆμ‹œλŠ” λΉ„μ–΄ μžˆμ§€λ§Œ, ꡬ문 μ•„λž˜μ—μ„œλŠ” 두 방법 λͺ¨λ‘ λ™μΌν•œ κ²°κ³Όλ₯Ό λ„μΆœν•΄κ°€λŠ” 방법을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

Defining a Class

μƒμ„±μž ν•¨μˆ˜λŠ” ν•¨μˆ˜ 자체λ₯Ό μ°Έμ‘°ν•˜μ—¬ μ—¬λŸ¬ λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ΄ˆκΈ°ν™”λ©λ‹ˆλ‹€. μ‹λ³„μžμ˜ 첫 번째 λ¬ΈμžλŠ” 관둀에 따라 λŒ€λ¬Έμžλ‘œ ν‘œμ‹œλ©λ‹ˆλ‹€.

constructor.js

// Initializing a constructor function
function Hero(name, level) {
    this.name = name;
    this.level = level;
}

이것을 클래슀 ꡬ문(class syntax)으둜 λ³€ν™˜ν•΄ 보면, 맀우 μœ μ‚¬ν•œ ꡬ쑰둜 λ˜μ–΄ μžˆμŒμ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

class.js

// Initializing a class definition
class Hero {
    constructor(name, level) {
        this.name = name;
        this.level = level;
    }
}

μƒμ„±μž ν•¨μˆ˜λŠ” initializer의 첫 번째 문자(선택 사항)의 λŒ€λ¬Έμž 및 ꡬ문에 λŒ€ν•œ μ΅μˆ™ν•¨ 톡해 객체 Blueprintλ₯Ό μ˜λ―Έν•œλ‹€λŠ” 것을 μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€. 클래슀 ν‚€μ›Œλ“œλŠ” 우리 κΈ°λŠ₯의 λͺ©ν‘œλ₯Ό 보닀 μ§μ„€μ μœΌλ‘œ μ „λ‹¬ν•©λ‹ˆλ‹€.

μ΄ˆκΈ°ν™” ꡬ문의 μœ μΌν•œ 차이점은 ν•¨μˆ˜ λŒ€μ‹  class ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜κ³  constroctor() λ©”μ„œλ“œ 내에 속성을 ν• λ‹Ήν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

Defining Methods

μƒμ„±μž κΈ°λŠ₯은 일반적으둜 μ•„λž˜ greet() λ°©λ²•μ—μ„œ λ³Ό 수 μžˆλ“―μ΄, μ΄ˆκΈ°ν™” λŒ€μ‹  ν”„λ‘œν† νƒ€μž…μ— 직접 λ©”μ†Œλ“œλ₯Ό ν• λ‹Ήν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

constructor.js

function Hero(name, level) {
    this.name = name;
    this.level = level;
}

// Adding a method to the constructor
Hero.prototype.greet = function() {
    return `${this.name} says hello.`;
}

클래슀λ₯Ό μ‚¬μš©ν•˜λ©΄ 문법, ꡬ문이 λ‹¨μˆœν™”λ˜κ³  λ©”μ„œλ“œλ₯Ό ν΄λž˜μŠ€μ— 직접 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ES6μ—μ„œ μ†Œκ°œν•œ 방법을 μ‚¬μš©ν•˜λ©΄ 선언을 μ •μ˜ν•˜λŠ” 것이 훨씬 더 μ½”λ“œλ“€μ΄ κ°„κ²°ν•΄μ§€κ²Œ λ©λ‹ˆλ‹€.

class.js

class Hero {
    constructor(name, level) {
        this.name = name;
        this.level = level;
    }

    // Adding a method to the constructor
    greet() {
        return `${this.name} says hello.`;
    }
}

μ΄λŸ¬ν•œ νŠΉμ„± 및 μ‹€ν–‰ 방법을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. new ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ Hero의 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€κ³  λͺ‡ 가지 값을 ν• λ‹Ήν•  κ²ƒμž…λ‹ˆλ‹€.

const hero1 = new Hero('Varg', 1);

console.log(hero1)λ₯Ό μ‚¬μš©ν•˜μ—¬ μƒˆ κ°œμ²΄μ— λŒ€ν•œ μžμ„Έν•œ 정보λ₯Ό 좜λ ₯ν•˜λ©΄ 클래슀 μ΄ˆκΈ°ν™”μ— λŒ€ν•΄ μžμ„Ένžˆ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

Output
Hero {name: "Varg", level: 1}
__proto__:
  β–Ά constructor: class Hero
  β–Ά greet: Ζ’ greet()

hero1의 호좜둜 constructor()와 greet()의 값에 λŒ€ν•œ 할당이 __proto__ λ˜λŠ” Prototype에 μ μš©λ˜μ—ˆλ‹€λŠ” 것을 console.log`μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

Extending a Class

μƒμ„±μž κΈ°λŠ₯ 및 클래슀의 이점은 μƒμœ„ ν•­λͺ©μ„ 기반으둜 μƒˆ 객체둜 ν™•μž₯ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ λΉ„μŠ·ν•˜μ§€λ§Œ λͺ‡ 가지 μΆ”κ°€ κΈ°λŠ₯ λ˜λŠ” κ·Έ μ΄μƒμ˜ νŠΉμ • κΈ°λŠ₯이 ν•„μš”ν•œ κ°œμ²΄μ— λŒ€ν•œ μ½”λ“œκ°€ λ°˜λ³΅λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μƒˆλ‘œμš΄ μƒμ„±μž function이 생성이 되면 call() λ©”μ„œλ“œλ₯Ό λΆ€λͺ¨μ—κ²Œ μ—°κ²°ν•΄μ€λ‹ˆλ‹€. 예λ₯Όλ“€μ–΄, MageλΌλŠ” classλ₯Ό λ§Œλ“€κ³  call()을 μ‚¬μš©ν•˜μ—¬ Hero 의 속성을 ν• λ‹Ήν•˜κ³ , μΆ”κ°€ 속성을 μΆ”κ°€ν•  κ²ƒμž…λ‹ˆλ‹€.

constructor.js

// Creating a new constructor from the parent
function Mage(name, level, spell) {
    // Chain constructor with call
    Hero.call(this, name, level);

    this.spell = spell;
}

μ—¬κΈ°μ„œ ν¬μΈνŠΈλŠ” HeroλŠ” Mage에 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€κ°€ 생성이 λ˜λ©΄μ„œ ν”„λ‘œνΌν‹°λ₯Ό ν• λ‹Ήλ°›κ²Œ λ©λ‹ˆλ‹€.

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

hero2λ₯Ό μ½˜μ†”μ— μ°μ–΄λ³΄κ²Œ 되면 Mageλ₯Ό 톡해 μƒˆλ‘œμš΄ μƒμ„±μžλΌ 생성이 된 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

Output
Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__:
    β–Ά constructor: Ζ’ Mage(name, level, spell)

ES6 클래슀 쀑 superλΌλŠ” ν‚€μ›Œλ“œκ°€ μžˆμŠ΅λ‹ˆλ‹€. 이 ν‚€μ›Œλ“œλŠ” callλŒ€μ‹  λΆ€λͺ¨ function에 λŒ€ν•œ κΈ°λŠ₯을 μ•‘μ„ΈμŠ€ν•˜κ²Œ λ©λ‹ˆλ‹€. λΆ€λͺ¨μ˜ classλ₯Ό ν™•μž₯ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ©λ‹ˆλ‹€.

class.js

// Creating a new class from the parent
class Mage extends Hero {
    constructor(name, level, spell) {
        // Chain constructor with super
        super(name, level);

        // Add a new property
        this.spell = spell;
    }
}

λ™μΌν•œ λ°©μ‹μœΌλ‘œ Mage에 μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

const hero2 = new Mage('Lejon', 2, 'Magic Missile');

hero2λ₯Ό μ½˜μ†”λ‘œ 찍어보면,

Output
Mage {name: "Lejon", level: 2, spell: "Magic Missile"}
__proto__: Hero
    β–Ά constructor: class Mage

좜λ ₯은 거의 λ™μΌν•©λ‹ˆλ‹€. 단, 클래슀 κ΅¬μ„±μ—μ„œ [Prototype](/Lee-hyuna/33-js-concepts-kr/wiki/Prototype)이 λΆ€λͺ¨(Hero)와 μ—°κ²°λ©λ‹ˆλ‹€. λ‹€μŒμ€ 전체 μ΄ˆκΈ°ν™” ν”„λ‘œμ„ΈμŠ€, μΆ”κ°€ 방법, μƒμ„±μž ν•¨μˆ˜ 및 클래슀의 상속을 λ‚˜λž€νžˆ λΉ„κ΅ν•œ κ²ƒμž…λ‹ˆλ‹€.

constructor.js

function Hero(name, level) {
    this.name = name;
    this.level = level;
}

// Adding a method to the constructor
Hero.prototype.greet = function() {
    return `${this.name} says hello.`;
}

// Creating a new constructor from the parent
function Mage(name, level, spell) {
    // Chain constructor with call
    Hero.call(this, name, level);

    this.spell = spell;
}

class.js

// Initializing a class
class Hero {
    constructor(name, level) {
        this.name = name;
        this.level = level;
    }

    // Adding a method to the constructor
    greet() {
        return `${this.name} says hello.`;
    }
}

// Creating a new class from the parent
class Mage extends Hero {
    constructor(name, level, spell) {
        // Chain constructor with super
        super(name, level);

        // Add a new property
        this.spell = spell;
    }
}

λ‘κ°œμ˜ 문법은 μƒλ‹Ήνžˆ λ‹€λ₯΄μ§€λ§Œ 두 방법 λͺ¨λ‘ κΈ°λ³Έ κ²°κ³ΌλŠ” 거의 λ™μΌν•©λ‹ˆλ‹€. 클래슀λ₯Ό 톡해 객체λ₯Ό 보닀 κ°„κ²°ν•˜κ²Œ μž‘μ„±ν•  수 있으며, μƒμ„±μž κΈ°λŠ₯은 hood μ•„λž˜μ—μ„œ λ°œμƒν•˜λŠ” μž‘μ—…μ„ 보닀 μ •ν™•ν•˜κ²Œ μ„€λͺ…ν•©λ‹ˆλ‹€.

κ²°λ‘ 

이 본문은 JavaScript μƒμ„±μž κΈ°λŠ₯κ³Ό ES6 클래슀 κ°„μ˜ μœ μ‚¬μ κ³Ό 차이점에 λŒ€ν•΄ μ•Œμ•„ λ³΄μ•˜μŠ΅λ‹ˆλ‹€. 클래슀 및 μƒμ„±μžλŠ” λͺ¨λ‘ ν”„λ‘œν† νƒ€μž… 기반 상속 언어인 JavaScript에 객체 지ν–₯ 상속 λͺ¨λΈμ„ λͺ¨λ°©ν•©λ‹ˆλ‹€.

효과적인 JavaScript κ°œλ°œμžκ°€ 되기 μœ„ν•΄μ„œλŠ” ν”„λ‘œν† νƒ€μž… 상속을 μ΄ν•΄ν•˜λŠ” 것이 무엇보닀 μ€‘μš”ν•©λ‹ˆλ‹€. React와 같은 인기 μžˆλŠ” JavaScript λΌμ΄λΈŒλŸ¬λ¦¬κ°€ 클래슀 ꡬ문을 자주 μ‚¬μš©ν•˜λ―€λ‘œ ν΄λž˜μŠ€μ— μ΅μˆ™ν•΄μ§€λŠ” 것이 맀우 μœ μš©ν•©λ‹ˆλ‹€.