์ƒ์„ฑ์ž ํ•จ์ˆ˜, ํ”„๋กœํ† ํƒ€์ž…

@choi2021 ยท December 12, 2022 ยท 31 min read

๐ŸŽˆ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ณผ ํ”„๋กœํ† ํƒ€์ž…

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

โœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

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

1) ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์€ ๊ฐ€์žฅ ์‰ฝ๊ฒŒ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ {}๋กœ ๋‚ด๋ถ€์— ๋„ฃ์„ ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ๋ฅผ ๋‹ด์•„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

const position = {
  x: 1,
  y: 2,
}

2) ์ƒ์„ฑ์ž ํ•จ์ˆ˜

์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” new์—ฐ์‚ฐ์ž๋ฅผ ์ด์šฉํ•ด ๊ฐ์ฒด, ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋ณด๋‹ค๋Š” ์ƒ๋Œ€์ ์œผ๋กœ ๋ณต์žกํ•˜๊ฒŒ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

2-1) Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜

Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ new ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ดํ›„์— ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ๋‚ด๋ถ€์— ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

const person = new Object()

person.name = `lee`
person.sayHello = function () {
  console.log(this.name)
}

Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ์™ธ์— ๋นŒํŠธ์ธ ๊ฐ์ฒด๋“ค๋„ new์™€ ํ•จ๊ป˜ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

const strObj = new String("youngjun")
console.log(strObj)

const numObj = new Number(123)
console.log(numObj)

const boolObj = new Boolean(true)
console.log(boolObj)

const func = new Function("x", "return x*x")
console.log(func)

const arr = new Array(1, 2, 3)
console.log(arr)

const regExp = new RegExp(/ab+c/i)
console.log(regExp)

2-2) ์‚ฌ์šฉ์ž ์ •์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜

ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์ธ์Šคํ„ด์Šค์— ์ถ”๊ฐ€ํ•  ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•œ ํ›„์— new ํ‚ค์›Œ๋“œ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

function Person(name) {
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
}
const person = new Person("youngjun")
console.log(person)

3) Object.create()

ํ”„๋กœํ† ํƒ€์ž…์˜ ์ƒ์†์„ ์ด์šฉํ•ด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ž์ฒด์ ์œผ๋กœ๋Š” ๋นˆ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์ง€๋งŒ, prototype์œผ๋กœ ์ „๋‹ฌ ๋ฐ›์€ ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

const obj1 = { a: 1, b: 2 }
const obj2 = Object.create(obj1)

console.log(obj2) // {}
console.log(obj2.a) // 1

๐Ÿ˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ํ•„์š”์„ฑ๊ณผ ๋™์ž‘๋ฐฉ์‹

๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•๋“ค ์ค‘์— ์™œ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์“ฐ์ด๋Š”์ง€์™€ ๋™์ž‘ ๋ฐฉ์‹์„ ์•Œ์•„๋ณด์ž.

์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ํ•„์š”์„ฑ

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

const person1 = {
  name: "youngjun",
  sayHello() {
    console.log(this.name)
  },
}

const person2 = {
  name: "minjae",
  sayHello() {
    console.log(this.name)
  },
}

์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์œ ์‚ฌํ•œ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•  ๋•Œ, ํ…œํ”Œ๋ฆฟ์„ ๋งŒ๋“ค๊ณ  ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์ฃผ์ž…๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๋ฉด ํŽธํ•˜์ง€ ์•Š์„๊นŒ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค. ์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋‹ค.

function Person(name) {
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
}
const person = new Person("youngjun")
console.log(person)

๋™์ž‘๋ฐฉ์‹

์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ 1) ์ธ์Šคํ„ด์Šค์ƒ์„ฑ 2) ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™” 3) ์ธ์Šคํ„ด์Šค ๋ฐ˜ํ™˜ ์„ธ ๊ฐ€์ง€ ๊ณผ์ •์œผ๋กœ ์ง„ํ–‰๋œ๋‹ค. ์œ„์˜ ์˜ˆ์ œ๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ณด์ž.

function Person(name) {
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
}
const person = new Person("youngjun")
console.log(person)

1) ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ์•”๋ฌต์ ์œผ๋กœ ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ this์™€ ๋ฐ”์ธ๋”ฉ์ด ๋œ๋‹ค.

function Person(name) {
  // 1) ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ, this์™€ ๋ฐ”์ธ๋”ฉ
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
}
const person = new Person("youngjun")
console.log(person)

2) ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™”

this์— ๋ฐ”์ธ๋”ฉ ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ดํ›„์— this๋ฅผ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™” ๊ณผ์ •์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

function Person(name) {
  // 1) ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ, this์™€ ๋ฐ”์ธ๋”ฉ
  // 2) ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™”
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
}
const person = new Person("youngjun")
console.log(person)

3) ์ธ์Šคํ„ด์Šค ๋ฐ˜ํ™˜

์ดˆ๊ธฐํ™” ๊ณผ์ •์ด ๋๋‚˜๋ฉด return์œผ๋กœ ์ ์ง€ ์•Š์•„๋„ ์•”๋ฌต์ ์œผ๋กœ this๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค. ์ด๋•Œ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ returnํ•˜๋ฉด ๋ช…์‹œํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ณ , ์›์‹œ๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์•”๋ฌต์ ์œผ๋กœ this๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

function Person(name) {
  // 1) ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ, this์™€ ๋ฐ”์ธ๋”ฉ
  // 2) ์ธ์Šคํ„ด์Šค ์ดˆ๊ธฐํ™”
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
  // 3) ์ธ์Šคํ„ด์Šค ๋ฐ˜ํ™˜
}

// ๋ช…์‹œ์ ์œผ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด ๋ฐ˜ํ™˜
function Person(name) {
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
  return {}
}
const person = new Person("youngjun")
console.log(person) // {}

//๋ช…์‹œ์ ์œผ๋กœ ์›์‹œ๊ฐ’ ๋ฐ˜ํ™˜
function Person(name) {
  this.name = name
  this.sayHello = function () {
    console.log(this.name)
  }
  return "hi"
}
const person = new Person("youngjun")
console.log(person) // Person { name: 'youngjun', sayHello: [Function (anonymous)] }

โ› ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ

์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜ํ•จ์ˆ˜์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑํ–ˆ์ง€๋งŒ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š”์ง€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ์บ๋ณด์ž.

ํ•จ์ˆ˜ ๊ฐ์ฒด์˜ [[call]]๊ณผ [[Construct]]

ํ•จ์ˆ˜๋Š” ๊ฐ์ฒด๋‹ค. ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์— ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋˜ ๊ฐ์ฒด์˜ ํŠน์„ฑ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

function bar() {}
bar.a = 1
console.log(bar.a) // 1

ํ•˜์ง€๋งŒ ํ•จ์ˆ˜ ๊ฐ์ฒด๋Š” ์ผ๋ฐ˜ ๊ฐ์ฒด์™€ ๋‹ค๋ฅด๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ณ  ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ๋„ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ์ด์œ ๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด์—๋Š” ์ผ๋ฐ˜ ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ [[call]]๊ณผ [[construct]]๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋•Œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€ ๋ชจ๋“  ํ•จ์ˆ˜๋Š” [[call]]์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๋ชจ๋“  ํ•จ์ˆ˜๊ฐ€ [[construct]]๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ [[construct]]๋ฅผ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜๋ฅผ constructor๋ผ๊ณ  ๋ถ€๋ฅด๊ณ  [[construct]]๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๋Š” ํ•จ์ˆ˜๋Š” non-constructor๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌ๋œ๋‹ค.

  • constructor: ํ•จ์ˆ˜ ์„ ์–ธ๋ฌธ, ํ•จ์ˆ˜ ํ‘œํ˜„์‹, ํด๋ž˜์Šค
  • non-constructor: ๋ฉ”์†Œ๋“œ ์ถ•์•ฝ, ํ™”์‚ดํ‘œ ํ•จ์ˆ˜

์ด๋ ‡๊ฒŒ ๋‚ด๋ถ€์ ์œผ๋กœ [[construct]]๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด new์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์–ธ์ œ๋“  ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฑฐ๋ผ๋ฉด ํ™”์‚ดํ‘œํ•จ์ˆ˜์™€ ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ๋Š” ๋ฉ”์†Œ๋“œ ์ถ•์•ฝ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๋” ์ข‹๋‹ค๊ณ  ์ƒ๊ฐ๋œ๋‹ค.

// ์ผ๋ฐ˜ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ์žํ•จ์ˆ˜๋กœ
function add(x, y) {
  return x + y
}

let inst = new add()
console.log(inst) //add{}

function createUser(name, role) {
  return { name, role }
}

inst = new createUser("lee", "admin")
console.log(inst) // { name: 'lee', role: 'admin' }

//์ƒ์„ฑ์žํ•จ์ˆ˜๋ฅผ ์ผ๋ฐ˜ํ•จ์ˆ˜๋กœ
function Circle(radius) {
  this.radius = radius
  this.getDiameter = function () {
    return 2 * this.radius
  }
}

const circle = Circle(5)
console.log(circle) // undefined
console.log(radius) // 5
console.log(getDiameter()) //10

์œ„ ์ฝ”๋“œ์—์„œ ์ผ๋ฐ˜ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ์žํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์ผ๋ฐ˜ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—์„œ๋Š” this๊ฐ€ window๊ฐ€ ๋˜์–ด ์ „์—ญ๊ฐ์ฒด์˜ ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ๋กœ ๋“ฑ๋ก๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๐ŸŽš ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๊ตฌ๋ถ„

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ผ๋ฐ˜ํ•จ์ˆ˜์™€ ์ƒ์„ฑ์žํ•จ์ˆ˜๋Š” ๊ตฌ๋ถ„ํ•˜๊ธฐ ํž˜๋“ค๊ธฐ ๋•Œ๋ฌธ์—, ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” Pascalํ‘œ๊ธฐ๋ฒ•์„ ์ด์šฉํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋‹จ์ˆœํžˆ ๋ช…๋ช…๋ฒ•์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— new.target์„ ์ด์šฉํ•ด new๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

new.target์€ new์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜๋ฉด ํ•จ์ˆ˜ ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ , ์ผ๋ฐ˜ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ๋Š” undefined๋กœ ๋‚˜ํƒ€๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ๊ฐ์— ๋”ฐ๋ฅธ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

function Circle(radius) {
  if (!new.target) {
    return new Circle(radius)
  }
  this.radius = radius
  this.getDiameter = function () {
    return 2 * this.radius
  }
}

const circle = Circle(5)
console.log(circle.getDiameter())

์œ„ ์ฝ”๋“œ์—์„œ new ํ‚ค์›Œ๋“œ ์—†์ด ํ˜ธ์ถœ๋˜์—ˆ์ง€๋งŒ new.target์„ ์ด์šฉํ•ด ์ƒ์„ฑ์žํ•จ์ˆ˜๋กœ ๋‹ค์‹œ ํ˜ธ์ถœ์‹œ์ผœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“  ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

โœจ ํ”„๋กœํ† ํƒ€์ž…

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

๐Ÿ™‹โ€โ™€๏ธ ํ”„๋กœํ† ํƒ€์ž…์ด๋ž€

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

prototype
prototype

๊ทธ๋Ÿฌ๋ฉด ํ”„๋กœํ† ํƒ€์ž…์ด ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์ง€๋Š” ์ง€ ์ •๋ฆฌํ•ด๋ณด์ž

ํ•จ์ˆ˜ ์„ ์–ธ

ํ•จ์ˆ˜์—๋Š” ๋‚ด๋ถ€ ์Šฌ๋กฏ์—[[call]]๊ณผ [[construct]]๊ณผ ๊ฐ™์ด [[prototype]]์ด ์กด์žฌํ•˜๋Š”๋ฐ ์ด๋Š” ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ, ํ•ด๋‹น ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์–ด ์งˆ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์†ํ•  ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค. prototype๊ฐ์ฒด๋Š” [[construct]]๋กœ ์ƒ์„ฑ์žํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ”„๋กœํ† ํƒ€์ž…๊ณผ ์ƒ์„ฑ์žํ•จ์ˆ˜๋Š” ๋‹จ๋…์œผ๋กœ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์„œ๋กœ prototype๊ณผ constructor์†์„ฑ์œผ๋กœ ํ•จ๊ป˜ ์กด์žฌํ•œ๋‹ค.

function
function

function Foo() {}
console.log(Foo.prototype) // {}
console.log(Foo.prototype.constructor) // [Function: Foo]

์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

์ƒ์„ฑ์žํ•จ์ˆ˜์— new ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๋ฉด ์ธ์Šคํ„ด์Šค๋Š” ํ”„๋กœํ† ํƒ€์ž…์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์† ๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ƒ์„ฑ์žํ•จ์ˆ˜์™€ ๋‹ค๋ฅด๊ฒŒ [[prototype]]์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜๋Š” ์—†์ง€๋งŒ __proto__๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ„์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

instance
instance

function Foo() {}
Foo.prototype.val = "hi"
console.log(Foo.prototype) // { val: 'hi' }
console.log(Foo.prototype.constructor) // [Function: Foo]

const obj1 = new Foo()
console.log(obj1) // Foo {}
console.log(obj1.val) // hi

obj1์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์—์„œ val ์†์„ฑ์„ ์ •์˜ํ•œ ์ ์ด ์—†์ง€๋งŒ ํ”„๋กœํ† ํƒ€์ž…์— ์ •์˜ํ•œ ๊ฒƒ์„ ์ƒ์†๋ฐ›์•„ obj1์—์„œ๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ™„ __proto__์™€ prototype

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

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

ํ•˜์ง€๋งŒ __proto__ ์†์„ฑ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํ† ํƒ€์ž…์„ ์ ‘๊ทผํ•  ๋•Œ Object.getPrototypeof๋ฅผ, ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒดํ•  ๋•Œ๋Š” Object.setPrototypeOf๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

const obj = Object.create(null) // ์ƒ์†์„ ์ด์šฉํ•ด ๋งŒ๋“  ๊ฐ์ฒด
console.log(obj.__proto__) // undefined

console.log(Object.getPrototypeOf(obj)) //null

const child = {}
const parent = { x: 1 }

Object.setPrototypeOf(child, parent)
console.log(obj2.x) // 1

prototype์€ ํ•จ์ˆ˜๊ฐ€ ๊ฐ€์ง€๋Š” ์†์„ฑ์œผ๋กœ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ๋งŒ๋“ค ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ๋˜์ง€ ๋ชปํ•˜๋Š”, [[construct]]๊ฐ€ ์—†๋Š” ํ™”์‚ดํ‘œํ•จ์ˆ˜๋‚˜ ๋ฉ”์†Œ๋“œ ์ถ•์•ฝํ‘œํ˜„์€ prototype์†์„ฑ์„ ๊ฐ€์ง€์ง€ ์•Š๊ณ , ํ”„๋กœํ† ํƒ€์ž…์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

const Person = name => {
  this.name = name
}

console.log(Person.hasOwnProperty("prototype")) //false

๋‘˜์„ ์ •๋ฆฌํ•˜๋ฉด __proto__๋Š” ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ prototype์€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ฐจ์ด๋ฅผ ๊ฐ€์ง„๋‹ค.

โ› ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ํ”„๋กœํ† ํƒ€์ž…

์•ž์„  ์„ค๋ช…์— ์ƒ์„ฑ์žํ•จ์ˆ˜์™€ ํ”„๋กœํ† ํƒ€์ž…์€ ํ•ญ์ƒ ํ•จ๊ป˜ ์ƒ์„ฑ๋œ๋‹ค๊ณ  ์„ค๋ช…ํ–ˆ๋‹ค. ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์ƒ์„ฑ์žํ•จ์ˆ˜์™€ ๋นŒํŠธ์ธ ์ƒ์„ฑ์žํ•จ์ˆ˜๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋‘๊ฐ€์ง€ ๋ฐฉ์‹์—์„œ ์ƒ์„ฑ์žํ•จ์ˆ˜๊ฐ€ ์–ธ์ œ ์ƒ์„ฑ๋˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

์‚ฌ์šฉ์ž ์ •์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜

console.log(Foo.prototype) // {}
function Foo(name) {
  this.name = name
}

์œ„ ์ฝ”๋“œ์—์„œ Fooํ•จ์ˆ˜๋Š” ํ‰๊ฐ€ ๋‹จ๊ณ„์—์„œ ์ „์—ญ ์Šค์ฝ”ํ”„์— ๋“ฑ๋ก๋˜๋ฉด์„œ ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ๋ฐ”๋กœ ์ดˆ๊ธฐํ™”๊ฐ€ ๋œ๋‹ค. ์ด๋•Œ ํ”„๋กœํ† ํƒ€์ž…๋„ ํ•จ๊ป˜ ์ƒ์„ฑ๋˜์–ด ๋ฐ”์ธ๋”ฉ ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Foo. prototype์„ ๋จผ์ € ํ˜ธ์ถœํ•ด๋„ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š๊ณ  ๊ฐ’์ด ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ค‘์š”ํ•œ ๊ฒƒ์€ "๋ชจ๋“  ๊ฐ์ฒด๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์—" ๋ฐ”์ธ๋”ฉ๋œ ํ”„๋กœํ† ํƒ€์ž…๋„ ์ž์‹ ์˜ ํ”„๋กœํ† ํƒ€์ž…์„ Object.Prototype์œผ๋กœ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.

๋นŒํŠธ์ธ ์ƒ์„ฑ์ž ํ•จ์ˆ˜

๋นŒํŠธ์ธ ์ƒ์„ฑ์žํ•จ์ˆ˜๋Š” Object, String, Number๋“ฑ ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜๋กœ ์ „์—ญ ๊ฐ์ฒด(๋ธŒ๋ผ์šฐ์ €: Window, NodeJS: Global) ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•จ๊ป˜ ์ƒ์„ฑ๋œ๋‹ค. ์ด๋•Œ ์‚ฌ์šฉ์ž ์ •์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒ์„ฑ์žํ•จ์ˆ˜๊ฐ€ ๋งŒ๋“ค์–ด์งˆ ๋•Œ ํ•จ๊ป˜ ํ”„๋กœํ† ํƒ€์ž…๋„ ๋งŒ๋“ค์–ด์ ธ ๋นŒํŠธ์ธ ์ƒ์„ฑ์žํ•จ์ˆ˜์˜ prototype์— ๋ฐ”์ธ๋”ฉ๋œ๋‹ค.

๐Ÿ‘“ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ์‹์— ๋”ฐ๋ฅธ ํ”„๋กœํ† ํƒ€์ž…

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

1) ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์€ Object.Prototype์„ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๊ฐ–๋Š”๋‹ค.

const obj = {}
console.log(obj.constructor === Object)

2) Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜

Object ์ƒ์„ฑ์žํ•จ์ˆ˜๋„ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๊ณผ ๋™์ผํ•˜๊ฒŒ Object.Prototype์„ ํ”„๋กœํ†  ํƒ€์ž…์œผ๋กœ ๊ฐ–๋Š”๋‹ค.

const Obj = new Object()
console.log(obj.constructor === Object)

3) ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๊ฐ์ฒด

์ƒ์„ฑ์žํ•จ์ˆ˜๋Š” ์ƒ์„ฑ๋  ๋•Œ ํ”„๋กœํ† ํƒ€์ž…์ด ๋ฐ”์ธ๋”ฉ ๋˜์–ด ์žˆ์–ด, ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฐ์ฒด๋Š” ์ƒ์„ฑ์žํ•จ์ˆ˜์˜ prototype ์†์„ฑ์— ๋ฐ”์ธ๋”ฉ๋œ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ–๋Š”๋‹ค. ์œ„ ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹๊ณผ ๋‹ค๋ฅธ ์ ์€ Object.Prototype์€ ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์ง€๋งŒ ์ƒ์„ฑ์žํ•จ์ˆ˜์™€ ๋ฐ”์ธ๋”ฉ๋œ ํ”„๋กœํ† ํƒ€์ž…์€ constructor ์†์„ฑ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

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

Person.prototype.sayHello = function () {
  console.log(`${this.name}`)
}

const me = new Person("Lee") // Lee
const you = new Person("Kim") // Kim
me.sayHello()

console.log(me.hasOwnProperty) // [Function: hasOwnProperty]

me์™€ you๋Š” ํ”„๋กœํ† ํƒ€์ž…์˜ sayHello๋ฅผ ์ƒ์† ๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ถ„๋ช… ๋ฐ”์ธ๋”ฉ๋œ Person.Prototype์—๋Š” ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ sayHello์™€ constructor๋งŒ ์†์„ฑ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผํ•˜๋Š”๋ฐ ์–ด๋–ป๊ฒŒ Object.Prototype์˜ hasOwnProperty๋„ ์ƒ์† ๋ฐ›์„ ์ˆ˜ ์žˆ์„๊นŒ?

๐Ÿ–‡ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ

์•ž์„  ์˜ˆ์ œ์—์„œ Person.Prototype์—๋Š” constructor๋งŒ ์žˆ์–ด์•ผ ํ•˜์ง€๋งŒ hasOwnProperty๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๊ฐ์ฒด์—์„œ ์ ‘๊ทผํ•˜๋ ค๋Š” ์†์„ฑ์ด ์—†์„ ๋•Œ์—๋Š” [[prototype]]์„ ์ด์šฉํ•ด, ์ƒ์†๋ฐ›์€ ๋ถ€๋ชจ์˜ ํ”„๋กœํผํ‹ฐ๋“ค์„ ์ˆœ์ฐจ์ ์œผ๋กœ ๊ฒ€์ƒ‰ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๊ณ„์†ํ•ด์„œ ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋Š” ๊ฒƒ์„ ํ”„ํ† ํ† ํƒ€์ž… ์ฒด์ธ์ด๋ผ๊ณ  ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ฒด์ด๋‹์ด ๊ฐ€๋Šฅํ•œ ์ด์œ ๋Š” ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ณ„์†ํ•ด์„œ ํƒ€๊ณ  ์˜ฌ๋ผ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ๊ฐ€์žฅ ๋์€ ํ•ญ์ƒ Object.prototype์œผ๋กœ Object.Protype์˜ ํ”„๋กœํ† ํƒ€์ž…์€ null๋กœ ํƒ์ƒ‰์ด ์ข…๋ฃŒ๋œ๋‹ค.

function Person(name, gender) {
  this.name = name
  this.gender = gender
  this.sayHello = function () {
    console.log("Hi! my name is " + this.name)
  }
}
const foo = new Person("Lee", "male")

console.log(foo.__proto__ === Person.prototype) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Person.__proto__ === Function.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ฒซ๋ฒˆ์งธ ํ˜ธ์ถœ์—์„œ ์ƒ์„ฑ์žํ•จ์ˆ˜์™€ ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐ™์€ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๊ณ , Person ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํ† ํƒ€์ž…์ด Object.prototype์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ๋นŒํŠธ์ธ ์ƒ์„ฑ์žํ•จ์ˆ˜์ธ Function์˜ ํ”„๋กœํ† ํƒ€์ž…๋„ Object.Prototype์ธ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

chain
chain

โœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ๊ณผ ์‰๋„์ž‰

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

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

Person.prototype.sayHello = function () {
  console.log(`Prototype ${this.name}`)
}

const me = new Person("lee")
me.sayHello = function () {
  console.log(`instance ${this.name}`)
}

me.sayHello() // instance lee

delete me.sayHello

me.sayHello() // Prototype lee

sayHello๋ฅผ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์—์„œ ์ฐพ์„ ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ์ธ์Šคํ„ด์Šค์—์„œ ์†์„ฑ์„ ์ฐพ๊ธฐ ๋•Œ๋ฌธ์— ๋จผ์ €instance lee๊ฐ€ ํ˜ธ์ถœ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ์ธ์Šคํ„ด์Šค์˜ sayHello๋ฅผ ์ œ๊ฑฐํ•œ ํ›„์—๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์„ ์ด์šฉํ•ด Person.prototype์˜ sayHello๋ฅผ ์ด์šฉํ•ด Prototype lee๊ฐ€ ํ˜ธ์ถœ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์Šค์ฝ”ํ”„์ฒด์ธ์—์„œ ๊ฐ™์€ ์ด๋ฆ„์˜ ์‹๋ณ„์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ๋„ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•œ๋‹ค.

๐Ÿ‘‰ ํ”„๋กœํ† ํƒ€์ž… ๋ฐ”๊พธ๊ธฐ

์•ž์„œ prototype ๊ณผ __proto__๋ฅผ ์ด์šฉํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๋‹ค. ์ด์ œ๋Š” ์ง์ ‘ ์ ‘๊ทผํ•ด์„œ ํ”„๋กœํ† ํƒ€์ž…์„ ๋ฐ”๊ฟ”๋ณด์ž

1) ์ƒ์„ฑ์žํ•จ์ˆ˜๋กœ ํ”„๋กœํ† ํƒ€์ž… ๋ฐ”๊พธ๊ธฐ

์ƒ์„ฑ์žํ•จ์ˆ˜์—์„œ ํ”„๋กœํ† ํƒ€์ž…์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” prototype์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

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

Person.prototype = {
  constructor: Person,
  sayHello() {
    console.log(this.name)
  },
}

const me = new Person("lee")

console.log(me.constructor === Person)

2) ์ธ์Šคํ„ด์Šค๋กœ ํ”„๋กœํ† ํƒ€์ž… ๋ฐ”๊พธ๊ธฐ

์ธ์Šคํ„ด์Šค์—์„œ ํ”„๋กœํ† ํƒ€์ž…์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” __proto__๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์•ž์„œ ์ •๋ฆฌํ•œ ๊ฒƒ์ฒ˜๋Ÿผ __proto__๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด๋„ ์žˆ์œผ๋ฏ€๋กœ Object.getPrototypeOf์™€ Object.setPrototypeOf๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

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

const me = new Person("lee")

const parent = {
  sayHello() {
    console.log(this.name)
  },
}

Object.setPrototypeOf(me, parent)
me.sayHello()

console.log(me.constructor === Person) // false
console.log(me.constructor === Object) // true

์œ„ ์ฝ”๋“œ์—์„œ me์˜ ํ”„๋กœํ† ํƒ€์ž…์ด ๋ฐ”๋€Œ๋ฉด์„œ ๊ธฐ์กด์˜ Person.Prototype์ด constructor๊ฐ€ ์•„๋‹ˆ๋ผ parent์˜ constructor์ธ Object.Prototype์ด constructor๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์œ„ ๋‘ ๊ฐ€์ง€์˜ ์ฐจ์ด์ ์€ ์ƒ์„ฑ์žํ•จ์ˆ˜์˜ prototype์ด ์ƒˆ๋กญ๊ฒŒ ์—ฐ๊ฒฐ๋œ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋ƒ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ง์ ‘ ํ”„๋กœํ† ํƒ€์ž…์„ ๋ฐ”๊ฟ”์„œ ์ƒ์†๊ด€๊ณ„๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์ง€๋งŒ, ์œ„ํ—˜ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋œ๋‹ค. ์ž์‹์ด ๋ถ€๋ชจ๋ฅผ ๋ฐ”๊พธ๋‹ค ๋ณด๋ฉด ๊ด€๊ณ„๊ฐ€ ๊ผฌ์ผ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์ ์œผ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ํ”„๋กœํ† ํƒ€์ž…์„ ๋ฐ”๊พธ์ง€ ์•Š๊ณ , ์ƒ์†๋ฐ›์€ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์–ด๋–ค ํ”„๋กœํ† ํƒ€์ž…์ด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์— ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœํ† ํƒ€์ž…์— ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ์žˆ๋Š” ์ง€ ์–ด๋–ป๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์„๊นŒ?

๐Ÿ˜‰ Instanceof

Instanceof ํ‚ค์›Œ๋“œ๋Š” ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์— ์ƒ์„ฑ์žํ•จ์ˆ˜์˜ ํ”„๋กœํ† ํƒ€์ž…์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

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

const me = new Person("Choi")

console.log(me instanceof Person) // true
console.log(me instanceof Object) // true

const parent = {}
Object.setPrototypeOf(me, parent)
console.log(me instanceof Person) // false
console.log(me instanceof Object) // true

์œ„ ์ฝ”๋“œ์—์„œ Object.setPrototypeOf์„ ์ด์šฉํ•ด me์˜ prototype์ด ๋ฐ”๋€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋ฐ”๋€Œ๊ณ  ๋‚œ ํ›„์— instanceOf๋ฅผ ์ด์šฉํ•ด ํ™•์ธํ–ˆ์„ ๋•Œ, ๊ธฐ์กด ํ”„๋กœํ† ํƒ€์ž…์ด์—ˆ๋˜ Person.Prototype์ด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์—์„œ ์‚ฌ๋ผ์ง€๊ฒŒ ๋˜์–ด false๋กœ, ์ƒˆ๋กญ๊ฒŒ ๋ถ€๋ชจ๊ฐ€ ๋œ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์˜ Prototype์ธ Object.Prototype์€ true ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

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

const parent = { x: 1 }
Person.prototype = parent

const me = new Person("hi")

console.log(parent.constructor === Person) //false
console.log(me) // { name: 'hi' }
console.log(me instanceof Person) //true

์ด ๋ถ€๋ถ„์„ ์ •๋ฆฌํ•˜๋ฉด์„œ ํ—ท๊ฐˆ๋ ธ๋˜ ๊ฒƒ์€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ ํ”„๋กœํ† ํƒ€์ž…์„ parent๋กœ ๋ฐ”๊พผ๋‹ค๊ณ  ํ•ด์„œ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๋งŒ๋“ค์–ด์ง„ ์ธ์Šคํ„ด์Šค์˜ ๋ชจ์Šต์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํ† ํƒ€์ž…๋งŒ ๋ฐ”๋€” ๋ฟ, me์ž์ฒด๊ฐ€ { x: 1 }์ด ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒˆ๋กญ๊ฒŒ ๋ฐ”๊พผ ํ”„๋กœํ† ํƒ€์ž…์˜ constructor๊ฐ€ ์ธ์Šคํ„ด์Šค์˜ ์ƒ์„ฑ์žํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์ง€ ์•Š์•„๋„ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์— ์กด์žฌํ•œ๋‹ค๋ฉด instanceOf๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๐Ÿ‘† Object.create

๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ๋งˆ์ง€๋ง‰ ๋ฐฉ๋ฒ•์ด์—ˆ๋˜ Object.create()๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ์ง์ ‘ ์ •ํ•ด์„œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ง์ ‘ ์ƒ์†์„ ์ •ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— new ํ‚ค์›Œ๋“œ ์—†์ด๋„ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ , ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋„ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

const obj1 = Object.create(null)
console.log(obj.toString()) // TypeError: obj.toString is not a function

const parent = { x: 1 }
const child = Object.create(parent)
console.log(child.x) // 1
console.log(Object.getPrototypeOf(child) === parent) // true

์œ„ ์ฝ”๋“œ์—์„œ null์„ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๋งŒ๋“  ๊ฐ์ฒด๋Š” ํ”„๋กœํ† ํƒ€์ž…์˜ ์ข…์ ์— ํ•ด๋‹นํ•˜๊ธฐ ๋•Œ๋ฌธ์— Object.Prototype์˜ ๋‚ด๋ถ€ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Object.create์— Parent๋ฅผ ์ด์šฉํ•ด child๋ฅผ ๋งŒ๋“ค๋ฉด, child๋Š” parent์˜ x์†์„ฑ์„ ์ƒ์† ๋ฐ›๊ณ  parent๋ฅผ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๐ŸŽฎ ์ •์  ์†์„ฑ/๋ฉ”์†Œ๋“œ

์ •์  ์†์„ฑ/๋ฉ”์†Œ๋“œ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ์†Œ์œ ํ•˜๋Š” ์†์„ฑ๊ณผ ๋ฉ”์†Œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธ์Šคํ„ด์Šค์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋Š” ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

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

Person.prototype.sayHello = function () {
  console.log(this.name)
}

Person.staticProp = `static Prop`
Person.staticMethod = function () {
  console.log("static method")
}

const me = new Person("choi")
Person.staticMethod() // static method
me.staticMethod() // TypeError: me.staticMethod is not a function

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

static
static

๐Ÿค— ๊ฐ์ฒด ์† ์†์„ฑ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ๊ณผ ๋‚˜์—ด

1) ์†์„ฑ ์กด์žฌ ์—ฌ๋ถ€

๊ฐ์ฒด์˜ ์†์„ฑ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ in์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ์ƒ์†๋˜๋Š” ์†์„ฑ๋“ค๋„ ๋‹ค ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

const Person = {
  name: "choi",
}

console.log("name" in Person) // true
console.log("hasOwnProperty" in Person) // true

๋งŒ์•ฝ ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ณ ์œ  ์†์„ฑ๋งŒ ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด hasOwnProperty๋ฅผ ์ด์šฉํ•ด์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const Person = {
  name: "choi",
}

console.log(Person.hasOwnProperty("name")) // true
console.log(Person.hasOwnProperty("hasOwnProperty")) //false

2) ๋‚˜์—ดํ•˜๊ธฐ

๊ฐ์ฒด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ๋‚˜์—ดํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ for~in ๊ตฌ๋ฌธ์ด ์žˆ๋‹ค. ์ด๋•Œ ์ฃผ์˜ํ•  ์ ์€ ๊ณ ์œ  ์†์„ฑ ๋ฟ ์•„๋‹ˆ๋ผ ์ƒ์† ๋ฐ›์€ ์†์„ฑ ์ค‘ [[Enumerable]]์ด true์ธ ๊ฐ’๋“ค๋„ ์—ด๊ฑฐํ•œ๋‹ค.

const Person = {
  name: "choi",
}

Object.setPrototypeOf(Person, { x: 1 })

for (const key in Person) {
  console.log(key)
}
// name
// x

๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง„ ์†์„ฑ๋“ค๋งŒ ๋‚˜์—ดํ•˜๋ ค ํ•œ๋‹ค๋ฉด Object.keys(),Object.values(),Object.entries()์™€ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

const Person = {
  name: "choi",
}

Object.setPrototypeOf(Person, { x: 1 })

console.log(Object.keys(Person)) // ["name"]
console.log(Object.values(Person)) // ["choi"]

[์ฐธ๊ณ ]

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