๐Ÿ“‹ ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive | 19์žฅ ํ”„๋กœํ† ํƒ€์ž… (1)

waterglassesยท2022๋…„ 4์›” 27์ผ
0
post-thumbnail

๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep Dive ๋„์„œ์˜ 19์žฅ์„ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋“ค์–ด๊ฐ€๋ฉฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๊ธฐ๋ฐ˜์˜ ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด๋ฃจ๊ณ  ์žˆ๋Š” ๊ฑฐ์˜ ๋ชจ๋“  ๊ฒƒ์ด ๊ฐ์ฒด์ด๋‹ค.

19.1 ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

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

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

const person = {
  name: 'Lee',
  address: 'Seoul'
}

console.log(person); // {name:'Lee", address: 'Seoul'}

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

19.2 ์ƒ์†๊ณผ ํ”„๋กœํ† ํƒ€์ž…

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

/// ์˜ˆ์ œ 19-03
function Circle(radius){
  this.radius = radius;
  this.getArea = function () {
    return Math.PI * this.radius ** 2;
  }
}

const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); // false

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

/// ์˜ˆ์ œ 19-04
function Circle(radius){
  this.radius = radius;
}

// ํ”„๋กœํ† ํƒ€์ž…์€ Circle ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype ํ”„๋กœํผํ‹ฐ์— ๋ฐ”์ธ๋”ฉ๋˜์–ด ์žˆ๋‹ค.
Circle.prototype.getArea = function () {
  return Math.PI * this.radius ** 2;
}

const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); // true

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

19.3 ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด

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

19.3.1 proto ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ

๋ชจ๋“  ๊ฐ์ฒด๋Š” __proto__ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ์ž์‹ ์˜ ํ”„๋กœํ† ํƒ€์ž…, ์ฆ‰ [[Prototype]] ๋‚ด๋ถ€ ์Šฌ๋กฏ์— ๊ฐ„์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

__proto__๋Š” ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋‹ค.
__proto__๋Š” getter/setter ํ•จ์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ์ ‘๊ทผ์ž ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž…์„ ์ทจ๋“ํ•˜๊ฑฐ๋‚˜ ํ• ๋‹นํ•œ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ __proto__ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž…์— ์ ‘๊ทผํ•˜๋ฉด getter [[Get]]์ด ํ˜ธ์ถœ๋˜๊ณ  ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž…์„ ํ• ๋‹นํ•˜๋ฉด setter ํ•จ์ˆ˜์ธ [[Set]]์ด ํ˜ธ์ถœ๋œ๋‹ค.

//์˜ˆ์ œ 19-06
const obj = {}
const parent = { x: 1};

// getter ํ•จ์ˆ˜์ธ get __proto__ ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด obj ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ์ทจ๋“
obj.__proto__;
// setter ํ•จ์ˆ˜์ธ set __proto__ ๊ฐ€ ํ˜ธ์ถœ๋˜์–ด obj ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒด
obj.__proto__ = parent;

console.log(obj.x); //1

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

// ์˜ˆ์ œ 19-07
const person = { name: 'Lee'};

// person rorcpsms __proto__ ํ”„๋กœํผํ‹ฐ๋ฅผ ์†Œ์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค. 
console.log(person.hasOwnProperty('__proto__')); //false

// ๋ชจ๋“  ๊ฐ์ฒด๋Š” ์ƒ์†์„ ํ†ตํ•ด `Object.prototype.__proto__` ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
console.log({}.__proto__ === Object.prototype); //true

__proto__ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž…์— ์ ‘๊ทผํ•˜๋Š” ์ด์œ 
์ƒํ˜ธ ์ฐธ์กฐ์— ์˜ํ•ด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋‹ค.

// ์˜ˆ์ œ 19-08
const parent = {};
const child = {};

// child์˜ ํ”„๋กœํ† ํƒ€์ž…์„ parent๋กœ ์„ค์ •
child.__proto__ = parent;
// parent์˜ ํ”„๋กœํ† ํƒ€์ž…์„ child๋กœ ์„ค์ •
parent.__proto__ = child; // TypeError: Cyclic __proto__ value

ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์€ ๋‹จ๋ฐฉํ–ฅ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด์•ผ ํ•œ๋‹ค. ์ฆ‰, ํ”„๋กœํผํ‹ฐ ๊ฒ€์ƒ‰ ๋ฐฉํ–ฅ์ด ํ•œ์ชฝ ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํ˜๋Ÿฌ๊ฐ€์•ผ ํ•œ๋‹ค.
why? ์ˆœํ™˜ ์ฐธ์กฐํ•˜๋Š” ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์ด ๋งŒ๋“ค์–ด์ง€๋ฉด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ ์ข…์ ์ด ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์—์„œ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•  ๋•Œ ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์ง€๊ธฐ ๋•Œ๋ฌธ์—

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

// ์˜ˆ์ œ 19-09
// obj๋Š” ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ์ข…์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ Object.__proto__๋ฅผ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์—†๋‹ค.
const obj = Object.create(null);
console.log(obj.__proto__); //undefined

// ๋”ฐ๋ผ์„œ __proto__๋ณด๋‹ค Object.getPrototypeOf ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์ข‹๋‹ค.
console.log(Obj.getPrototypeOf(obj)); // null

const obj2 = {};
const parent = { x: 1};

Object.getPrototypeOf(obj2); // obj2.__proto__;
Object.setPrototypeOf(obj2, parent); //obj2.__proto__ = parent;

19.3.2 ํ•จ์ˆ˜ ๊ฐ์ฒด์˜ prototype ํ”„๋กœํผํ‹ฐ

ํ•จ์ˆ˜ ๊ฐ์ฒด๋งŒ์ด ์†Œ์œ ํ•˜๋Š” prototypeํ”„๋กœํผํ‹ฐ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

//์˜ˆ์ œ 19-11
// ํ•จ์ˆ˜ ๊ฐ์ฒด๋Š” prototype ํ”„๋กœํผํ‹ฐ๋ฅผ ์†Œ์œ 
(function () {}).hasOwnProperty('prototype'); //true

// ์ผ๋ฐ˜ ๊ฐ์ฒด๋Š” prototype ํ”„๋กœํผํ‹ฐ๋ฅผ ์†Œ์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
(() {}).hasOwnProperty('prototype'); // false

์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋Š” ํ•จ์ˆ˜, ์ฆ‰ non-constructor์ธ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜์™€ ES6 ๋ฉ”์„œ๋“œ ์ถ•์•ฝ ํ‘œํ˜„์œผ๋กœ ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ๋Š” prototype ํ”„๋กœํผํ‹ฐ๋ฅผ ์†Œ์œ ํ•˜์ง€ ์•Š์œผ๋ฉฐ ํ”„๋กœํ† ํƒ€์ž…๋„ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” __proto__ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ์™€ ํ•จ์ˆ˜ ๊ฐ์ฒด๋งŒ์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” prototype ํ”„๋กœํผํ‹ฐ๋Š” ๊ฒฐ๊ตญ ๋™์ผํ•œ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

// ์˜ˆ์ œ 19-13
// ์ƒ์„ฑ์ž ํ•จ์ˆ˜
function Person(name){
  this.name = name;
}
const me = new Person('Lee');

// ๊ฒฐ๊ตญ Person.prototype๊ณผ me.__proto__๋Š” ๊ฒฐ๊ตญ ๋™์ผํ•œ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
console.log(Person.prototype === me.__proto__); // true

19.3.3 ํ”„๋กœํ† ํƒ€์ž…์˜ constructor ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜

๋ชจ๋“  ํ”„๋กœํ† ํƒ€์ž…์€ contructor ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ–๋Š”๋‹ค. ์ด contructor ํ”„๋กœํผํ‹ฐ๋Š” prototype ํ”„๋กœํผํ‹ฐ๋กœ ์ž์‹ ์„ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

// ์˜ˆ์ œ 19-14
// ์ƒ์„ฑ์ž ํ•จ์ˆ˜
function Person(name){
  this.name = name;
}
const me = new Person('Lee');
console.log(me.constructor === Person); // true

19.4 ๋ฆฌํ„ฐ๋Ÿด ํ‘œ๊ธฐ๋ฒ•์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์™€ ํ”„๋กœํ† ํƒ€์ž…

๋ฆฌํ„ฐ๋Ÿด ํ‘œ๊ธฐ๋ฒ•์— ์˜ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ์‹๊ณผ ๊ฐ™์ด ๋ช…์‹œ์ ์œผ๋กœ new ์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ์‹๋„ ์žˆ๋‹ค.

// ์˜ˆ์ œ 19-16 : ๋ฆฌํ„ฐ๋Ÿด๋กœ ์ƒ์„ฑ
// ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด
const obj = {};

// ํ•จ์ˆ˜ ๋ฆฌํ„ฐ๋Ÿด
const add = function (a, b) { return a + b; };

// ๋ฐฐ์—ด ๋ฆฌํ„ฐ๋Ÿด
const arr = [1, 2, 3];

// ์ •๊ทœํ‘œํ˜„์‹ ๋ฆฌํ„ฐ๋Ÿด
const regexp = /is/ig;

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

// obj ๊ฐ์ฒด๋Š” Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ƒ์„ฑํ•œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋กœ ์ƒ์„ฑํ–ˆ๋‹ค.
const obj = {};

// ํ•˜์ง€๋งŒ obj ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋‹ค.
console.log(obj.constructor === Object); // true

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

Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ๊ฐ์ฒด ์ƒ์„ฑ

์œ„์— ์‚ฌ์ง„์—์„œ 2๋ฒˆ์„ ๋ณด๋ฉด ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ undefined, null์„ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜์—ฌ ํ˜ธ์ถœํ•˜๋ฉด ์ถ”์ƒ ์—ฐ์‚ฐ OrdinaryObjectCreate๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Object.prototype์„ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๊ฐ–๋Š” ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

// ์˜ˆ์ œ 19-18
// 1. new.target์ด undefined๋‚˜ Object๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ
// ์ธ์Šคํ„ด์Šค -> Foo.prototype -> Object.prototype ์ˆœ์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์ด ์ƒ์„ฑ๋œ๋‹ค.
class Foo extends Object {}
new Foo(); // Foo {}

// 2. Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•œ ๊ฐ์ฒด ์ƒ์„ฑ
// Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” new ์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„๋„ new ์—ฐ์‚ฐ์ž์™€ ํ•จ๊ป˜ ํ˜ธ์ถœํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.
// ์ธ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜์ง€ ์•Š์•˜์„ ๋•Œ ์ถ”์ƒ ์—ฐ์‚ฐ OrdinaryObjectCreate๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
let obj = new Object();
console.log(obj); // {}

// 3. ์ธ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋œ ๊ฒฝ์šฐ์—๋Š” ์ธ์ˆ˜๋ฅผ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
// Number ๊ฐ์ฒด ์ƒ์„ฑ
obj = new Object(123);
console.log(obj); // Number {123}

// String  ๊ฐ์ฒด ์ƒ์„ฑ
obj = new Object('123');
console.log(obj); // String {"123"}

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์ด ํ‰๊ฐ€๋  ๋•Œ์—๋Š” ์ƒ ์—ฐ์‚ฐ OrdinaryObjectCreate๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ์ •์˜๋˜์–ด ์žˆ๋‹ค.

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋กœ ๊ฐ์ฒด ์ƒ์„ฑ

์ด์ฒ˜๋Ÿผ Object ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ํ˜ธ์ถœ๊ณผ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์˜ ํ‰๊ฐ€๋Š” ์ถ”์ƒ ์—ฐ์‚ฐ OrdinaryObjectCreate๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋นˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ ์—์„œ ๋™์ผํ•˜๋‚˜, new.target์˜ ํ™•์ธ์ด๋‚˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ฒ˜๋ฆฌ ๋“ฑ ์„ธ๋ถ€ ๋‚ด์šฉ์€ ๋‹ค๋ฅด๋‹ค.

๋”ฐ๋ผ์„œ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” Object์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ค.

Ref

  • ์ด์›…๋ชจ ์ €, โŒœ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Deep DiveโŒŸ, ์œ„ํ‚ค๋ถ์Šค
  • ECMAScriptยฎ
profile
๋งค ์ˆœ๊ฐ„ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€