๐Ÿ‘ฉ‍๐Ÿ’ป/JavaScript

[JavaScript] ํ•จ์ˆ˜ ์ƒ์„ฑ์ž์™€ ํด๋ž˜์Šค์˜ ์ฐจ์ด

ํ•œ๋‚˜ 2021. 5. 9. 21:35

ํ•จ์ˆ˜ ์ƒ์„ฑ์ž(Constructor Functions)๋ž€?

ํ•จ์ˆ˜ ์ƒ์„ฑ์ž๋Š” ์—ฌ๋Ÿฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ๋Š” 'ํด๋ž˜์Šค'์™€ ๋™์˜์–ด๋‹ค. ์–ด๋–ค ๊ฒฝ์šฐ ์‚ฌ๋žŒ๋“ค์€ ์ฐธ์กฐ ํƒ€์ž…(Reference Types), ํด๋ž˜์Šค(Classes), ๋ฐ์ดํ„ฐ ํƒ€์ž…, ์•„๋‹ˆ๋ฉด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ์„ฑ์ž๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ํด๋ž˜์Šค์— ์•„์ง ์ต์ˆ™ํ•˜์ง€ ์•Š๋‹ค๋ฉด, ์–ด๋–ค ์†์„ฑ(properties)๊ณผ ํ–‰๋™(functions)์„ ์ •์˜ํ•˜๋„๋ก ํ•ด์ฃผ๊ณ , ๊ทธ ์†์„ฑ๊ณผ ํ–‰๋™์„ ํ†ตํ•ด ์—ฌ๋Ÿฌ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ์ƒ์„ฑ์ž๋ผ๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค. ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด๋กœ์„œ ์ง‘์„ ์ง“๊ธฐ ์œ„ํ•œ ์ฒญ์‚ฌ์ง„์ด๋ผ๋Š” ๋น„์œ ๋ฅผ ๋งŽ์ด ํ•œ๋‹ค. ์—ฌ๋Ÿฌ ์ง‘์ด ๋‹จ ํ•˜๋‚˜์˜ ์ฒญ์‚ฌ์ง„์œผ๋กœ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋„ ๋‹จ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค.

function Person(name, position) {
    this.name = name,
    this.position = position
}

ํ•จ์ˆ˜ ์ด๋ฆ„์€ ์˜๋ฌด๋Š” ์•„๋‹ˆ์ง€๋งŒ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด naming convention์œผ๋กœ ์ž๋ฆฌ์žก์•˜๋‹ค. ๋˜, ๋ณดํ†ต ํ•จ์ˆ˜๋Š” ๊ด„ํ˜ธ์™€ ํ•จ๊ป˜ ํ˜ธ์ถœํ•˜๊ณ  ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” new ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

const hannah = new Person('Hannah Yoo', programmer)
const jisoo = new Person('Jisoo Han', 'student')

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” Person์ด๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ๋‘ ๊ฐœ ์ƒ์„ฑํ•˜๊ณ  ์žˆ๋‹ค.

new ํ‚ค์›Œ๋“œ์™€ ํ•จ๊ป˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ, this๋Š” ์ƒ์„ฑ๋˜๊ณ  ์žˆ๋Š” ๋ฐ”๋กœ ๊ทธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.

Methods

๋ฉ”์†Œ๋“œ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ์•ˆ์—์„œ ์†์„ฑ์— ํ•จ์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๋ฉด์„œ ์ •์˜๋œ๋‹ค.

function Person(name) {
    this.name = name;
    this.hi = function () {console.log(`Hi, My name is ${this.name}`)}
}
const hannah = new Person('Hannah Yoo');
hannah.hi(); // Hi, My name is Hannah Yoo

์—ฌ๊ธฐ์„œ hi ์†์„ฑ์€ ํ• ๋‹น๋œ ํ•จ์ˆ˜์ด๋‹ค. Person ๊ฐ์ฒด๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ this ํ‚ค์›Œ๋“œ๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ๋œ Person ๊ฐ์ฒด์— ์‘๋‹ตํ•  ๊ฒƒ์ด๋‹ค.

 

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ •์˜๋œ๋‹ค ํ•ด๋„ ์ด๋Ÿฐ ์ ‘๊ทผ๋ฒ•์€ ์•ฝ๊ฐ„ ๊ท€์ฐฎ๋‹ค. Person ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ๋งˆ๋‹ค ๊ทธ ๊ฐ์ฒด์˜ hi ํ”„๋กœํผํ‹ฐ์— ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋˜๊ณ , ํ• ๋‹น๋œ๋‹ค. ๋งŒ์ผ ์šฐ๋ฆฌ๊ฐ€ 5๊ฐœ์˜ Person ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค์น˜๋ฉด, ๊ฐ์ž ๋ชจ๋‘๊ฐ€ ๊ฐ™์€ ์ผ์„ ํ•˜๋Š” ์ž์‹ ๋งŒ์˜ hi ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ๋” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์€ hi ์†์„ฑ์„ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ Person ๊ฐ์ฒด๋Š” ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ๋œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ํ•จ์ˆ˜์˜ prototype์„ ์จ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

function Person(name) {
    this.name = name;
}

Person.prototype.hi = function () {
    console.log('hi my name is' + this.name)
}
const hannah = new Person('Hannah Yoo')
const jisoo = new Person('Jisoo Han')

hannah.hi();
jisoo.hi();

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋ชจ๋“  ํ•จ์ˆ˜๋Š” 'prototype'์ด๋ผ๊ณ  ํ•˜๋Š” ์†์„ฑ์ด ์žˆ๋Š”๋ฐ,์ด๋Š” ๊ฑฐ์˜ ๋นˆ ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•œ๋‹ค ๋งํ•  ์ˆ˜ ์žˆ๋‹ค. Person ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ๋งˆ๋‹ค ์ด ๊ฐ์ฒด๋Š” Person.prototype์— ์„ ์–ธ๋œ ์–ด๋–ค ์†์„ฑ์ด๋“ , ๋ฉ”์†Œ๋“œ๋“  ์ƒ์†๋ฐ›๊ฒŒ ๋œ๋‹ค.

์œ„ ์˜ˆ์‹œ๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ ์ ์„ ์ˆ˜๋„ ์žˆ๋‹ค.

function Person(name) {
    this.name = name;
}
Person.prototype = {
    constructor: Person,
    hi() {
        console.log('hi my name is' + this.name)
    }
}

์—ฌ๋Ÿฌ ๋ฒˆ Person.prototype์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๊ทธ๋ƒฅ Person.prototype ๊ฐ์ฒด๋ฅผ ์žฌ์ •์˜ํ•˜๋Š” ๊ฒŒ ๋‚ซ๋‹ค. ์•ž์„œ prototype์ด ๊ฑฐ์˜ ๋นˆ ๊ฐ์ฒด๋ผ๊ณ  ์–ธ๊ธ‰ํ–ˆ๋Š”๋ฐ, ์ •ํ™•ํ•˜๊ฒŒ ๋งํ•˜์ž๋ฉด, prototype์€ constructor๋ผ๋Š” ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ์ด๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋กœ prototype์„ ๋ฎ์–ด์”Œ์šด๋‹ค๋ฉด, ์ด constructor ์†์„ฑ๋„ resetํ•ด์•ผ ํ•œ๋‹ค.

์™œ Prototype์— ์จ์•ผ ํ•˜๋Š” ๊ฑธ๊นŒ?

prototype ์œ„์˜ ๊ทธ ์–ด๋–ค ๊ฒƒ์ด๋“  ๋ชจ๋“  ํ•ด๋‹น ์ƒ์„ฑ์ž ์ธ์Šคํ„ด์Šค ๊ฐ์ฒด ์‚ฌ์ด์— ๊ณต์œ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์šฐ๋ฆฌ๋Š” prototype์— ์„ ์–ธ๋œ ๋ฉ”์†Œ๋“œ๋ž„์ง€ ์ƒ์„ฑ์ž ๊ฐ์ฒด ์œ„์— ์ €์žฅ๋œ ์†์„ฑ๋งŒ์„ ๋ณด๊ณค ํ•œ๋‹ค. ๋ฉ”์†Œ๋“œ๋Š” ๊ณต์œ ๋œ ํ–‰๋™์–‘์‹์œผ๋กœ ๊ฐ ๊ฐ์ฒด๋Š” ์ž์‹ ๋งŒ์˜ ์œ ์ผํ•œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์—†๋‹ค. ํ•˜์ง€๋งŒ, ๊ฐ ๊ฐ์ฒด๋Š” ์ž์‹ ๋งŒ์˜ ์†์„ฑ์„ ๊ฐ€์ ธ์•ผ ํ•  ๋•Œ๋„ ์žˆ๋Š” ๋ฒ•์ด๋‹ค. prototype์ด ์•„๋‹ˆ๋ผ ๊ฐ์ฒด ์ž์ฒด์— ์ •์˜๋œ ์†์„ฑ์€ "own properties"๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค.

ES6 classes

ES6 ๋•๋ถ„์— ์šฐ๋ฆฌ๋Š” ์œ„ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ class ๋ฌธ๋ฒ•์œผ๋กœ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

class Person {
    constructor(name) {
    this.name = name;
    }
    hi() {
        console.log('..')
    }
}

์—ฌ๊ธฐ์„œ hi() ๋Š” Person.prototype์— ์ €์žฅ๋œ๋‹ค.

Property Lookups

๋งŒ์ผ ์šฐ๋ฆฌ๊ฐ€ ๊ฐ์ฒด์™€ ์ƒ์„ฑ์ž์˜ prototype์— ๊ฐ™์€ ์ด๋ฆ„์˜ ์†์„ฑ์„ ์„ ์–ธํ•˜๋ฉด ์–ด๋–ค ์ผ์ด ๋ฒŒ์–ด์งˆ๊นŒ?

function Person(name) {
    this.name = name;
    this.walk = function () {
        console.log('moon walking')
    }
}

Person.prototype.walk = function () {
    console.log('normal walking')
};

const mj = new Person('Michael Jackson');
mj.walk();

์ด ์˜ˆ์ œ์—์„œ๋Š”, walk ์ด๋ผ๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ Person ์ธ์Šคํ„ด์Šค์™€ Person.prototype์— ๊ฐ๊ฐ ์„ ์–ธ๋˜์—ˆ๋‹ค. ์ฝ˜์†”์—๋Š” ๋ญ๋ผ๊ณ  ์ฐํž๊นŒ?

JavaScript๋Š” ์šฐ์„  ๊ฐ์ฒด ์ž์‹ ์˜ "own property"๋ถ€ํ„ฐ ์ฐพ์œผ๋ ค ํ•œ๋‹ค. ๋งŒ์ผ own property๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด, ํ•ด๋‹น ์†์„ฑ์ด ์‚ฌ์šฉ๋œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋งŒ๋“  ํ•จ์ˆ˜์˜ prototype์„ ์ฐพ์•„๋ณด๋ ค ํ•  ๊ฒƒ์ด๋‹ค.

๋”ฐ๋ผ์„œ ์œ„ ์˜ˆ์ œ์—์„œ๋Š” mj ๊ฐ์ฒด ์ž์ฒด์—์„œ walk ๊ฐ€ ๋ฐœ๊ฒฌ๋˜๊ณ , ์ฝ˜์†”์—๋Š” 'moon walking'์ด ์ฐํž ๊ฒƒ์ด๋‹ค. ๋งŒ์ผ Person ๊ฐ์ฒด๊ฐ€ ์•„๋ž˜์ฒ˜๋Ÿผ ์ƒ๊ฒผ๋‹ค๋ฉด, ๊ฐ์ฒด ์ž์ฒด์— walk ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์œผ๋‹ˆ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” walk ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐœ๊ฒฌ๋˜๋Š” Person.prototype์„ ์ฐพ๊ฒŒ ๋˜๊ณ , 'normal walking'์ด ์ฝ˜์†”์— ์ฐํž ๊ฒƒ์ด๋‹ค.

function Person(name) {
    this.name = name;
}

์ƒ์†

๋งŒ์ผ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์˜ ์–ธ์–ด๋ฅผ ๊ณต๋ถ€ํ•œ ์‚ฌ๋žŒ์ด๋ผ๋ฉด, ์ƒ์†์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ•  ๊ฒƒ์ด๋‹ค. Animal์ด๋ผ๋Š” ์ƒ์„ฑ์ž๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž.

function Animal() {}
Animal.prototype.eat = function () {
    console.log('eating')
};

์ด๋ฒˆ์—๋Š” Cat ์ƒ์„ฑ์ž๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž.

function Cat() {
    Cat.prototype.meow = function () {
        console.log('meowing');
    }
};

Cat์€ ๋™๋ฌผ์˜ ํ•œ ์ข…๋ฅ˜์ด๋‹ˆ, Animal๋กœ๋ถ€ํ„ฐ ํ™•์žฅ๋œ Cat์„ ๊ฐ–๊ณ ์ž ํ•œ๋‹ค. ์ƒ์†์„ ํ•˜๊ธฐ ์œ„ํ•œ ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

function Animal() {}
Animal.prototype.eat = function () {
    console.log('eating')
}
function Cat(){}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function () {
    console.log('meowing');
}

์˜ˆ์ „์— ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์˜ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด, ๋ถ„๋ช… ์ด ๋Œ€๋ชฉ์—์„œ ์ด๊ฒŒ ๋Œ€์ฒด ๋ญ”๊ฐ€ ํ•˜๊ณ  ์ƒ๊ฐํ•  ๊ฒƒ์ด๋‹ค. ๊ต‰์žฅํžˆ ํˆฌ๋ฐ•ํ•ด๋ณด์ด์ง€ ์•Š๋‚˜. ๊ฐ์‚ฌํ•˜๊ฒŒ๋„ ES6/ES2015์˜ ํด๋ž˜์Šค๊ฐ€ ์ด ๊ณผ์ •์„ ํ›จ์”ฌ ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

class Animal {
    eat() {
        console.log('eating')
    }
}

class Cat extend Animal () {
    meow() {
        console.log('meowing')
    }
}

Native Constructor Functions & Their Shorthand (literal) Conterparts

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” Stirng, Number, Boolean, Array, Function, Object, RegExp, Date๋ฅผ ํฌํ•จํ•ด์„œ ์ƒ์„ฑ์ž์ฒ˜๋Ÿผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์—ฌ๋Ÿฌ ๋นŒํŠธ์ธ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

const str = new String('some string');
// OR
const str = 'some string'; // literal syntax
const age = new Number(25);
// OR
const age = 25; // literal syntax
const person = new Object();
// OR
const person = {}; // literal syntax
const x = new Boolean(false);
const x = false; // literal syntax
const add = new Function('a', 'b', 'return a+b');
const add = function (a, b) {
    return a + b;
}; // literal syntax

๋„ค์ดํ‹ฐ๋ธŒ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด numbers, strings, objects, booleans, functions๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๊ณ  ํ•ด๋„ ์–ธ์ œ๋‚˜ ๋ฆฌํ„ฐ๋Ÿด ์‹ ํƒ์Šค๊ฐ€ ๋” ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์ ์ด๋‹ค.

Extending Native Constructors

๋„ค์ดํ‹ฐ๋ธŒ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋„ ํ™•์žฅ๋  ์ˆ˜ ์žˆ๋‹ค. ์ปค์Šคํ…€ String ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“  ํ›„์—, ๋ฏธ๋ž˜์— ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ทธ ๋ฉ”์„œ๋“œ๋ฅผ ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ฒŒ implementํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๊ฐ€ ์˜ˆ์ƒํ•œ ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋‹ˆ ๊ทธ๋‹ค์ง€ ์ถ”์ฒœ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , prototype๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฐฐ์›Œ๋ณผ ๋งŒํ•œ ๊ฐ€์น˜๋Š” ์žˆ๋‹ค.

String.prototype.dasherize = function () {
    return this.replace(/\s/g, '-');
}
'hello world'.dasherize(); // hello-world

ํด๋ž˜์Šค๋ž€?

ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ผ์ข…์˜ ํ…œํ”Œ๋ฆฟ์ด๋‹ค. ํด๋ž˜์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์••์ถ•ํ•œ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํด๋ž˜์Šค๋Š” prototype์— ๊ธฐ๋ฐ˜ํ•˜์ง€๋งŒ, ES5์˜ ํด๋ž˜์Šค ๊ฐ™์€ ์‹œ๋งจํ‹ฑ๊ณผ ๊ณต์œ ๋˜์ง€ ์•Š๋Š” ๋ฌธ๋ฒ•๊ณผ ์‹œ๋งจํ‹ฑ์„ ๊ฐ€์ง„๋‹ค.

 

ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ธฐ[์„ ์–ธํ•˜๊ธฐ]

ํ•จ์ˆ˜ ํ‘œํ˜„์‹๊ณผ ํ•จ์ˆ˜ ์„ ์–ธ์‹์„ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํด๋ž˜์Šค๋Š” ์‚ฌ์‹ค 'ํŠน๋ณ„ํ•œ ํ•จ์ˆ˜'๋กœ, ํด๋ž˜์Šค ์‹ ํƒ์Šค๋Š” ํด๋ž˜์Šค ํ‘œํ˜„์‹๊ณผ ํด๋ž˜์Šค ์„ ์–ธ์‹ ๋‘ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ง„๋‹ค.

ํด๋ž˜์Šค ์„ ์–ธ์‹ Class declarations

ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ํ•œ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ํด๋ž˜์Šค ์„ ์–ธ์‹์ด๋‹ค. ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํด๋ž˜์Šค์˜ ์ด๋ฆ„๊ณผ ํ•จ๊ป˜ class ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์•„๋ž˜์˜ ์˜ˆ์‹œ์—์„œ๋Š” Rectangle์ด ๋œ๋‹ค.

class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
}

ํ•จ์ˆ˜ ์„ ์–ธ์‹(function declarations)๊ณผ ํด๋ž˜์Šค ์„ ์–ธ์‹(class declaration) ์‚ฌ์ด์˜ ์ค‘์š”ํ•œ ์ฐจ์ด์ ์€ ํ•จ์ˆ˜ ์„ ์–ธ์‹์ด ํ˜ธ์ด์ŠคํŒ…๋˜๊ณ , ํด๋ž˜์Šค ์„ ์–ธ์‹์€ ๊ทธ๋ ‡์ง€ ๋ชปํ•œ๋‹ค๋Š” ์ ์ด๋‹ค. ์šฐ์„  ํด๋ž˜์Šค๋ฅผ ์„ ์–ธํ•œ ๋’ค ๊ทธ ํ›„์— ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•„๋ž˜ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ReferenceError๋ฅผ ์ถœ๋ ฅํ•  ๊ฒƒ์ด๋‹ค.

const p = new Rectangle(); // Reference Error
class Rectangle {}

ํด๋ž˜์Šค ํ‘œํ˜„์‹ Class expression

ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด๋‹ค. ํด๋ž˜์Šค ํ‘œํ˜„์‹์€ ์ด๋ฆ„ ๋ถ™์—ฌ์ง€๊ฑฐ๋‚˜, ์ต๋ช…์œผ๋กœ ๋งŒ๋“ค์–ด์งˆ ์ˆ˜๋„ ์žˆ๋‹ค. named ํด๋ž˜์Šค ํ‘œํ˜„์‹์— ๋ถ™์—ฌ์ง„ ์ด๋ฆ„์€ ํด๋ž˜์Šค ๋ฐ”๋””์— ์ง€์—ญ์ ์ด๋‹ค. (ํด๋ž˜์Šค์˜ name ์†์„ฑ์„ ํ†ตํ•ด ๊ฒ€์ƒ‰๋  ์ˆ˜๋Š” ์žˆ๋‹ค. ์ธ์Šคํ„ด์Šค์˜ name ์†์„ฑ์— ์˜ํ•ด์„œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค)

// unnamed
let Rectangle = class {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
}
console.log(Rectangle.name); // Rectangle

// named
let Rectangle = class Rectangle2 {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
};
console.log(Rectangle.name); // Rectangle2

ํด๋ž˜์Šค ํ‘œํ˜„์‹๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ˜ธ์ด์ŠคํŒ… ๊ทœ์น™์— ์ ์šฉ๋ฐ›๋Š”๋‹ค. ์šฐ์„  ์„ ์–ธํ•œ ๋’ค์— ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค.

Class body and method definitions

ํด๋ž˜์Šค ๋ฐ”๋””๋Š” {} ๋กœ ๊ฐ์‹ธ์ง„ ๋ถ€๋ถ„์„ ๋งํ•œ๋‹ค. ์ด ๋ถ€๋ถ„์€ ๋ฉ”์†Œ๋“œ์™€ constructor ๊ฐ™์€ ํด๋ž˜์Šค ๋ฉค๋ฒ„๋ฅผ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค.

strict mode

ํด๋ž˜์Šค ๋ฐ”๋””๋Š” ์—„๊ฒฉ ๋ชจ๋“œ ์•ˆ์—์„œ ์‹คํ–‰๋œ๋‹ค.

Constructor

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

Prototype methods

class Rectangle {
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
    // getter
    get area() {
        return this.calcArea();
    }
    // method
    calcArea() {
        return this.height * this.width;
    }
}

const square = new Rectangle(10, 10);
console.log(square.area); // 100

Generator methods

class Polygon {
    constructor(...sides) {
        this.sides = sides;
    }
    // method
    getSides() {
        for(const side of this.sides) {
            yield side;
        }
    }
}

const pentagon = new Polygon(1, 2, 3, 4, 5);
console.log([...pentagon.getSides()]); // [1, 2, 3, 4, 5]

Static methods and properties

static ํ‚ค์›Œ๋“œ๋Š” ํด๋ž˜์Šค์˜ static method์™€ static property๋ฅผ ์ •์˜ํ•œ๋‹ค. Static ๋ฉค๋ฒ„๋Š” ์ด ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”(instantiating)ํ•˜์ง€ ์•Š๊ณ  ํ˜ธ์ถœ๋œ๋ฉฐ, ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ํ†ตํ•ด ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. Static methods๋Š” ์ข…์ข… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์“ฐ์ด๋ฉฐ, Static properties๋Š” ์บ์‹œ๋‚˜ fixed-configuration, ๋˜๋Š” ์ธ์Šคํ„ด์Šค ์ „์ฒด์— ๋ณต์‚ฌ๋  ํ•„์š”๊ฐ€ ์—†๋Š” ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•ด ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ธ๋‹ค.

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    static displayName = 'Point';
    static distance(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;
    return Math.hypot(dx, dy)
    }
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined

console.log(Point.displayName); // 'Point'
console.log(Point.distance(p1, p2)); // 7.0710678118654755

ํ”„๋กœํ† ํƒ€์ž…๊ณผ static methods๋กœ this ๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ

๊ฐ€๋ น ๋ณ€์ˆ˜์— ๋ฉ”์„œ๋“œ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ์ด๋ฅผ ๋ถ€๋ฅด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, static ๋˜๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๋ฅผ this ๋ฅผ ์œ„ํ•œ value ์—†์ด ํ˜ธ์ถœํ–ˆ์„ ๋•Œ, this ๊ฐ’์€ ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ undefined ์ผ ๊ฒƒ์ด๋‹ค. 'use strict' ๊ตฌ๋ฌธ์ด ์—†์–ด๋„ ๊ฐ™์€ ๋ฐ˜์‘์ด ๋‚˜์˜จ๋‹ค. class ๋ฐ”๋””๋Š” ํ•ญ์ƒ ์—„๊ฒฉ ๋ชจ๋“œ ๋‚ด์—์„œ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

class Animal {
    speak() {
        return this;
    }
    static eat() {
        return this;
    }
}

let obj = new Animal();
obj.speak(); // the Animal object
let speak = obj.speak; 
speak(); // undefined

Animal.eat(); // class Animal
let eat = Animal.eat;
eat(); // undefined

 

Reference

davidtang.io/javascript-constructor-functions-and-classes/

 

JavaScript Constructor Functions and Classes

The fundamentals of constructor functions and ES6 classes

davidtang.io

javascript.info/classes

 

Classes

 

javascript.info