[๐Ÿ“– ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋”ฅ๋‹ค์ด๋ธŒ] 19์žฅ. ํ”„๋กœํ† ํƒ€์ž… - 2

๋…ธ์˜์™„ยท2023๋…„ 11์›” 13์ผ
0

JavaScript(Deep Dive)

๋ชฉ๋ก ๋ณด๊ธฐ
15/23
post-thumbnail

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

1. ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ

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

// ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ
Person.prototype.sayHello = function() {
  console.log(`Hi My name is ${this.name}`)
};

const me = new Person('Lee')

// hasOwnProperty๋Š” Object.prototype์˜ ๋ฉ”์„œ๋“œ๋‹ค.
console.log(me.hasOwnProperty('name')); // true

Person ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•ด ์ƒ์„ฑ๋œ me ๊ฐ์ฒด๋Š” Object.prototype์˜ ๋ฉ”์„œ๋“œ์ธ hasOwnProperty๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์€ me ๊ฐ์ฒด๊ฐ€ Person.prototype๋ฟ๋งŒ ์•„๋‹ˆ๋ผ Object.prototype๋„ ์ƒ์†๋ฐ›์•˜๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

Person.protype์˜ ํ”„๋กœํ† ํƒ€์ž…์€ Object.prototype์ด๋‹ค. ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํ† ํƒ€์ž…์€ ์–ธ์ œ๋‚˜ Object.prototype์ด๋‹ค.

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

ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ƒ์†์„ ๊ตฌํ˜„ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ์ตœ์ƒ์œ„์— ์œ„์น˜ํ•˜๋Š” ๊ฐ์ฒด๋Š” ์–ธ์ œ๋‚˜ Object.prototype์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋ชจ๋“  ๊ฐ์ฒด๋Š” Object.prototype์„ ์ƒ์† ๋ฐ›๋Š”๋‹ค. Object.prototype์„ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ์ข…์  ์ด๋ผ ํ•œ๋‹ค.

ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์€ ์ƒ์†๊ณผ ํ”„๋กœํผํ‹ฐ ๊ฒ€์ƒ‰์„ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ์ด์— ๋ฐ˜ํ•ด ํ”„๋กœํผํ‹ฐ๊ฐ€ ์•„๋‹Œ ์‹๋ณ„์ž๋Š” ์Šค์ฝ”ํ”„ ์ฒด์ธ์—์„œ ๊ฒ€์ƒ‰ ์Šค์ฝ”ํ”„ ์ฒด์ธ์€ ์‹๋ณ„์ž ๊ฒ€์ƒ‰์„ ์œ„ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

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

2. ์˜ค๋ฒ„๋ผ์ด๋”ฉ๊ณผ ํ”„๋กœํผํ‹ฐ ์ƒˆ๋„์ž‰

const Person = (function () {
  // ์ƒ์„ฑ์ž ํ•จ์ˆ˜
  function Person(name) {
    this.name = name;
  }

  // ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ
  Person.prototype.sayHello = function () {
    console.log(`Hi! My name is ${this.name}`);
  };

  // ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜
  return Person;
}());

const me = new Person('Lee');

// ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ
me.sayHello = function () {
  console.log(`Hey! My name is ${this.name}`);
};

// ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์— ์˜ํ•ด ๊ฐ€๋ ค์ง„๋‹ค.
me.sayHello(); // Hey! My name is Lee

ํ”„๋กœํ† ํƒ€์ž…์ด ์†Œ์œ ํ•œ ํ”„๋กœํผํ‹ฐ(๋ฉ”์„œ๋“œ ํฌํ•จ)๋ฅผ ํ”„๋กœํฌํƒ€์ž… ํ”„๋กœํผํ‹ฐ, ์ธ์Šคํ„ด์Šค๊ฐ€ ์†Œ์œ ํ•œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

ํ”„๋กœํ† ํƒ€์ž… ํ”„๋กœํผํ‹ฐ์™€ ๊ฐ™์€ ์ด๋ฆ„์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ธ์Šคํ„ด์Šค์— ์ถ”๊ฐ€ํ•˜๋ฉด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์„ ๋”ฐ๋ผ ํ”„๋กœํ† ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ํ”„๋กœํ† ํƒ€์ž…์„ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ๋กœ ์ถ”๊ฐ€.

์ด๋•Œ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ sayHello๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ sayHello๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ–ˆ๊ณ  ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ sayHello๋Š” ๊ฐ€๋ ค์ง„๋‹ค. ์ด์ฒ˜๋Ÿผ ์ƒ์†๊ด€๊ณ„์— ์˜ํ•ด ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ฐ€๋ ค์ง€๋Š” ํ˜„์ƒ์„ ํ”„๋กœํผํ‹ฐ ์„€๋„์ž‰์ด๋ผ ํ•œ๋‹ค.

๐Ÿ’ก ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด๋ž€?

์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์žฌ์ •์˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹

๐Ÿ‘‰ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ฒฝ์šฐ

// ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
delete me.sayHello;
// ์ธ์Šคํ„ด์Šค์—๋Š” sayHello ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
me.sayHello(); // Hi! My name is Lee

์œ„ ์ฝ”๋“œ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ sayHello๊ฐ€ ์‚ญ์ œ๋œ๋‹ค.

๐Ÿ‘‰ ๋‹ค์‹œ ํ•œ๋ฒˆ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ญ์ œ

// ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์„ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ญ์ œ๋˜์ง€ ์•Š๋Š”๋‹ค.
delete me.sayHello;
// ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
me.sayHell(); // Hi! My name is Lee

ํ•˜์œ„ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝ ๋˜๋Š” ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๋‹ค์‹œ ๋งํ•ด ํ•˜์œ„ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด get ์•ก์„ธ๋Š” ํ—ˆ์šฉ๋˜๋‚˜ set ์•ก์„ธ์Šค๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค.

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

// ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ ๋ณ€๊ฒฝ
Person.prototype.sayHello - function() {
  	console.log(`Hey! My name is ${this.name}`)
}
me.sayHello();

// ํ”„๋กœํ† ํƒ€์ž… ๋งค์„œ๋“œ ์‚ญ์ œ
delete Person.prototype.sayHello;
me.sayHello(); // TypeError: me.sayHello is not a function

3. ํ”„๋กœํ† ํƒ€์ž…์˜ ๊ต์ฒด

ํ”„๋กœํ† ํƒ€์ž…์€ ์ž„์˜์˜ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค ์ด๊ฒƒ์€ ๋ถ€๋ชจ ๊ฐ์ฒด์ธ ํ”„๋กœํ† ํƒ€์ž…์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธ.์ด๋Ÿฌํ•œ ํŠน์ง•์„ ํ™œ์šฉํ•˜์—ฌ ๊ฐ์ฒด๊ฐ„์˜ ์ƒ์† ๊ด€๊ณ„๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

3-1. ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•œ ํ”„๋กœํ† ํƒ€์ž…์˜ ๊ต์ฒด

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

  // โ‘  ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒด
  Person.prototype = {
    sayHello() {
      console.log(`Hi! My name is ${this.name}`);
    }
  };

  return Person;
}());

const me = new Person('Lee');

โ‘ ์—์„œ person.prototypep์— ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ํ• ๋‹น ์ด๋Š” Person ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•  ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด๋กœ ๊ต์ฒดํ•œ ๊ฒƒ์ด๋‹ค.

ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๊ต์ฒดํ•œ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์—๋Š” constructor ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†๋‹ค. ๋”ฐ๋ผ์„œ me ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ฉด Person์ด ์•„๋‹Œ Object๊ฐ€ ๋‚˜์˜จ๋‹ค.

// ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒดํ•˜๋ฉด constructor ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๊ฐ„์˜ ์—ฐ๊ฒฐ์ด ํŒŒ๊ดด๋œ๋‹ค.
console.log(me.constructor === Person); // false
// ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์„ ๋”ฐ๋ผ Object.prototype์˜ constructor ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ฒ€์ƒ‰๋œ๋‹ค.
console.log(me.constructor === Object); // true

ํŒŒ๊ดด๋œ constructor ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๊ฐ„์˜ ์—ฐ๊ฒฐ ๋˜์‚ด๋ฆฌ๊ธฐ

const Person = (function () {
  function Person(name) {
    this.name = name;
  }
  
  // ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒด
  Person.prototype = {
    // constructor ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๊ฐ„์˜ ์—ฐ๊ฒฐ์„ ์„ค์ •
    constructor: Person,
    sayHello() {
      console.log(`Hi My name is ${this.name}`)
    }
  };
  
  return Person;
}());

const me = new Person('Lee');

// constructor ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
console.log(me.constructor === Person); // true
console.log(me.constructor === Object); // false

3-2. ์ธ์Šคํ„ด์Šค์— ์˜ํ•œ ํ”„๋กœํ† ํƒ€์ž…์˜ ๊ต์ฒด

์ธ์Šคํ„ด์Šค __proto__ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ ๋˜๋Š” Object.getPrototypeOf ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค.

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

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

const me = new Person('Lee');

// ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒดํ•  ๊ฐ์ฒด
const parent = {
  sayHello() {
    console.log(`Hi! My name is ${this.name}`);
  }
};

// โ‘  me ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ parent ๊ฐ์ฒด๋กœ ๊ต์ฒดํ•œ๋‹ค.
Object.setPrototypeOf(me, parent);
// ์œ„ ์ฝ”๋“œ๋Š” ์•„๋ž˜์˜ ์ฝ”๋“œ์™€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.
// me.__proto__ = parent;

me.sayHello(); // Hi! My name is Lee

โ‘ ์—์„œ me ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ parent ๊ฐ์ฒด๋กœ ๊ต์ฒด

// ํ”„๋กœํ† ํƒ€์ž…์„ ๊ต์ฒดํ•˜๋ฉด constructor ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๊ฐ„์˜ ์—ฐ๊ฒฐ์ด ํŒŒ๊ดด๋œ๋‹ค.
console.log(me.constructor === Person); // false
console.log(me.constructor === Object); // true

๐Ÿ‘‰ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•œ ํ”„๋กœํ† ํƒ€์ž… ๊ต์ฒด vs ์ธ์Šคํ„ด์Šค์— ์˜ํ•œ ํ”„๋กœํ† ํƒ€์ž… ๊ต์ฒด

๐Ÿ‘‰ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์˜ํ•œ ํ”„๋กœํ† ํƒ€์ž… ๊ต์ฒด vs ์ธ์Šคํ„ด์Šค์— ์˜ํ•œ ํ”„๋กœํ† ํƒ€์ž… ๊ต์ฒด

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

// ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ๊ต์ฒดํ•  ๊ฐ์ฒด
const person = {
  // constructor ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜ ๊ฐ„์˜ ์—ฐ๊ฒฐ์„ ์„ค์ •
  constructor : Person,
  sayHello() {
    console.log(`Hi! My name is ${this.name}`);
  }
};

// ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype ํ”„๋กœํผํ‹ฐ์™€ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ„์˜ ์—ฐ๊ฒฐ์„ ์„ค์ •
Person.prototype = parent;

// me ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์„ parent ๊ฐ์ฒด๋กœ ๊ต์ฒดํ•œ๋‹ค.
Object.setPrototypeOf(me, parent);
// ์œ„ ์ฝ”๋“œ๋Š” ์•„๋ž˜์˜ ์ฝ”๋“œ์™€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.
// me.__proto__ = parent;

me.sayHello(); // Hi! My name is Lee

// constructor ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
console.log(me.constructor === Person); // true
console.log(me.constructor === Object); // false

// ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ต์ฒด๋œ ํ”„๋กœํ† ํƒ€์ž…์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.
console.log(Person.prototype === Obejct.getPrototypeOf(me)); // true

4. instanceof ์—ฐ์‚ฐ์ž

instanceof ์—ฐ์‚ฐ์ž๋Š” ์ดํ•ญ ์—ฐ์‚ฐ์ž๋กœ ์ขŒ๋ณ€์— ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š”, ์šฐ๋ณ€์— ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹๋ณ„์ž๋ฅผ ํ”ผ์—ฐ์‚ฐ์ž๋กœ ๋ฐ›๋Š”๋‹ค. ๋งŒ์•ฝ ์šฐ๋ณ€์˜ ํ”ผ์—ฐ์‚ฐ์ž๊ฐ€ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ TypeError๊ฐ€ ๋ฐœ์ƒ.

๊ฐ์ฒด instanceof ์ƒ์„ฑ์ž ํ•จ์ˆ˜

์šฐ๋ณ€์˜ ์ƒ์„ฑ์ž ํ•จ์ˆ˜์˜ prototype์— ๋ฐ”์ธ๋”ฉ๋œ ๊ฐ์ฒด๊ฐ€ ์ขŒ๋ณ€์˜ ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ ์ƒ์— ์กด์žฌํ•˜๋ฉด true๋กœ ํ‰๊ฐ€ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ false๋กœ ํ‰๊ฐ€

// ์ƒ์„ฑ์ž ํ•จ์ˆ˜
function Person(name) {
  this.name = name;
}

const me = new Person('Lee');

// Person.prototype์ด me ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ ์ƒ์— ์กด์žฌํ•˜๋ฏ€๋กœ true๋กœ ํ‰๊ฐ€
console.log(me instanceof Person); // true

// Object.prototype์ด me ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ ์ƒ์— ์กด์žฌํ•˜๋ฏ€๋กœ true๋กœ ํ‰๊ฐ€
console.log(me instanceof Object); // true

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

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

5. ์ง์ ‘ ์ƒ์†

5-1. Object.create์— ์˜ํ•œ ์ง์ ‘ ์ƒ์†

Object.create ๋ฉ”์„œ๋“œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž…์„ ์ง€์ •ํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ. Object.create ๋ฉ”์„œ๋“œ๋„ ๋‹ค๋ฅธ ๊ฐ์ฒด ์ƒ์„ฑ ๋ฐฉ์‹๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ถ”์ƒ ์—ฐ์‚ฐ OrdinarayObjectCreate๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

Object.create ๋ฉ”์„œ๋“œ์˜ ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋Š” ์ƒ์„ฑํ•  ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•  ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ

Object.create ๋ฉ”์„œ๋“œ์˜ ๋‘ ๋ฒˆ์žฌ ๋งค๊ฐœ๋ณ€์ˆ˜์—๋Š” ์ƒ์„ฑํ•  ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ ํ‚ค์™€ ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด๋กœ ์ด๋ค„์ง„ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

// ํ”„๋กœํ† ํƒ€์ž…์ด null์ธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ์ข…์ ์— ์œ„์น˜.
// obj -> null
let obj = Object.create(null);
console.log(Object.getPrototypeOf(obj) === null); // true
// Object.prototype์„ ์ƒ์†๋ฐ›์ง€ ๋ชปํ•œ๋‹ค.
console.log(obj.toString()); // TypeError: obj.toString is not a function

// obj -> Object.prototype -> null
// obj = {};์™€ ๋™์ผํ•˜๋‹ค.
obj = Object.create(Object.proototype);
console.log(Object.getProitotypeOf(obj) === Object.prototype); // true

// obj -> Object.prototype -> null
// obj = {};์™€ ๋™์ผํ•˜๋‹ค
obj = Object.create(Object.prototype);
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

// obj -> Object.prototype -> null
// obj = { x: 1 };์™€ ๋™์ผํ•˜๋‹ค.
obj = Object.create(Object.prototype, {
  x: {value: 1, writable: true, enumerable: true, configurable: ture }
});
// ์œ„ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๋™์ผํ•˜๋‹ค.
// obj = Object.create(Object.prototype);
// obj.x = 1;
console.log(obj.x); // 1
console.log(Object.getPrototypeof(obj) === Object.prototype); // true

const myProto = { x: 10 };
// ์ž„์˜์˜ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ƒ์†๋ฐ›๋Š”๋‹ค.
// obj -> myProto -> Object.prototype -> null
obj = Object.create(myProto);
console.log(obj.x); // 10
console.log(Object.getPrototypeOf(obj) === myProto); // true

// ์ƒ์„ฑ์ž ํ•จ์ˆ˜
function Person(name) {
  this.name = name;
}
// obj -> Person.prototype -> Objectprototype ->  null
// obj = new Person('Lee')์™€ ๋™์ผํ•˜๋‹ค.
obj = Object.create(Person.prototype);
obj.name = 'Lee'
console.log(obj.name); // Lee
console.log(Object.getPrototypeOf(obj) === Person.prootype); // true

๐Ÿ‘‰ object.create ๋ฉ”์„œ๋“œ์˜ ์žฅ์ 

  • new ์—ฐ์‚ฐ์ž๊ฐ€ ์—†์ด๋„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ”„๋กœํ† ํƒ€์ž…์„ ์ง€์ •ํ•˜๋ฉด์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋„ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

โ— Object.prototype์˜ ๋นŒํŠธ์ธ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ์ฒด๊ฐ€ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

Object.create ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ์ข…์ ์— ์œ„์น˜ํ•˜๋Š” ๊ฐœ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ

// ํ”„๋กœํ† ํƒ€์ž…์ด null์ธ ๊ฐ์ฒด, ์ฆ‰ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์˜ ์ข…์ ์— ์œ„์น˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
const obj = Object.create(null);
obj.a = 1;

console.log(Object.getPrototypeOf(obj) === null); // true

// obj๋Š” Object.prototype์˜ ๋นŒํŠธ์ธ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
console.log(obj.hasOwnProperty('a'));
// TypeError: obj.hasOwnProperty is not a function

// ์œ„์™€ ๊ฐ™์€ TypeError๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์œ„ํ—˜ ์—†์• ๊ธฐ ์œ„ํ•ด Object.prototype์˜ ๋นŒํŠธ์ธ ๋ฉ”์„œ๋“œ ์ง์ ‘ ํ˜ธ์ถœ.
// Object.prototype์˜ ๋นŒํŠธ์ธ ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด๋กœ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.
console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // true

5-2. ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋‚ด๋ถ€์—์„œ __proto__์— ์˜ํ•œ ์ง์ ‘ ์ƒ์†

๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ๋‚ด๋ถ€์—์„œ __proto__ ์ ‘๊ทผ์ž ํ”„๋กœํ„ฐํ”ผ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ์ƒ์† ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

const myProto = { x: 10 };

// ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์— ์˜ํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ ํ”„๋กœํ† ํƒ€์ž…์„ ์ง€์ •ํ•˜์—ฌ ์ง์ ‘ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค,
const obj = {
  y: 20,
  // ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ƒ์†๋ฐ›๋Š”๋‹ค.
  // obj -> myProto -> Object.prototype -> null
  __proto__: myProto
};
/*  ์œ„ ์ฝ”๋“œ ์•„๋ž˜์™€ ๋™์ผ
const obj = Object.create(myProto, {
	y: {value: 20, writable: true, enumerable: true, configurable: true}
    });
    */

console.log(obj.x, obj.); // 10 20
console.log(Object.getPrototypeOf(obj) === myProto); // true

6. ์ •์  ํ”„๋กœํผํ‹ฐ / ๋ฉ”์„œ๋“œ

์ •์  ํ”„๋กœํผํ‹ฐ / ๋ฉ”์„œ๋“œ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ์ฐธ์กฐ / ํ˜ธ์ถœ ํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ / ๋ฉ”์„œ๋“œ๋ฅผ ๋งํ•œ๋‹ค.

// ์ƒ์„ฑ์ž ํ•จ์ˆ˜
fucntion Person(name) {
  this.name = name;
}

// ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ
Person.prototype.sayHello = fucntion() {
  console.log(`Hi! My name is ${this.name}`)
};

// ์ •์  ํ”„๋กœํผํ‹ฐ
Person.staticProp = 'static prop'

// ์ •์  ๋ฉ”์„œ๋“œ
Person.staticMethod = function () {
  console.log('staticMethod');
}

const me = new Person('Lee');

// ์ƒ์„ฑ์ž ํ•จ์‰ ์ถ”๊ฐ€ํ•œ ์ •์  ํ”„๋กœํผํ‹ฐ / ๋ฉ”์„œ๋“œ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋กœ ์ฐธ์กฐ / ํ˜ธ์ถœ ํ•œ๋‹ค.
Person.staticMethod(); // staticMethod

// ์ •์  ํ”„๋กœํผํ‹ฐ / ๋ฉ”์„œ๋“œ๋Š” ์ƒ์„ฑ์ž ํ•จ์ˆ˜๊ฐ€ ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค๋กœ ์ฐธ์กฐ / ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค.
// ์ธ์Šคํ„ด์Šค๋กœ ์ฐธ์กฐ / ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ / ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์ƒ์— ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
me.staticMethod(); // TypeError: me.staticMethod is not a function

// Object.create๋Š” ์ •์  ๋ฉ”์„œ๋“œ๋‹ค.
const obj = Object.create({ name: 'noh'});

// Object.prototype.hasOwnProperty๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๋‹ค.
obj.hasOwnProperty('name'); // false

Object.create ๋ฉ”์„œ๋“œ๋Š” ์ •์  ๋ฉ”์„œ๋“œ์ด๊ณ , Obejct.prototype.hasOwnproperty ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœํ† ํƒ€์ž…์˜ ๋ฉ”์„œ๋“œ์ด๋‹ค.

//  ์ธ์Šคํ„ด์Šค / ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ this๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ทธ ๋ฉ”์„œ๋“œ๋Š” ์ •์ ๋ฉ”์„œ๋“œ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
function Foo() {}

// ํ”„ํ† ํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ
// this๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๋Š” ์ •์  ๋ฉ”์„œ๋“œ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ๋„ ๋™์ผํ•œ ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
Foo.prototype.x = function () {
  conosole.log('x');
}

const foo = new Foo();
// ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
foo.x(); // x

// ์ •์  ๋ฉ”์„œ๋“œ
Foo.x = function () {
  console.log('x');
}

// ์ •์  ๋ฉ”์„œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
Foo.x(); // x

7. ํ”„๋กœํผํ‹ฐ ์กด์žฌ ํ™•์ธ

7-1. in ์—ฐ์‚ฐ์ž

in ์—ฐ์‚ฐ์ž๋Š” ๊ฐ์ฒด ๋‚ด์— ํŠน์ • ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•œ๋‹ค.

// ์‚ฌ์šฉ๋ฒ•
/**
 * key: ํ”„๋กœํผํ‹ฐ ํ‚ค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด
 * object: ๊ฐ์ฒด๋กœ ํ‰๊ฐ€๋˜๋Š” ํ‘œํ˜„์‹
 * */
key in object
const person = {
  name: "noh",
  address: "Seoul",
};

// person ๊ฐ์ฒด์— name ํ”„๋กœํผํ‹ฐ ์กด์žฌ
console.log('name' in person); // true
// person ๊ฐ์ฒด์— address ํ”„๋กœํผํ‹ฐ ์กด์žฌ
console.log('address' in person); // true
// person ๊ฐ์ฒด์— age ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
console.log('age' in person); // fasle

in ์—ฐ์‚ฐ์ž๋Š” ํ™•์ธ ๋Œ€์ƒ ๊ฐ์ฒด๊ฐ€ ์ƒ์†๋ฐ›์€ ๋ชจ๋“  ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ™•์ธํ•˜๋ฏ€๋กœ ์ฃผ์˜๊ฐ€ ํ•„์š”.

console.log('toString' in person); // true

in ์—ฐ์‚ฐ์ž๊ฐ€ person ๊ฐ์ฒด๊ฐ€ ์†ํ•œ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ ์ƒ์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ํ”„๋กœํ† ํƒ€์ž…์—์„œ toString ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฒ€์ƒ‰ํ–ˆ๊ธฐ ๋•Œ๋ฌธ. toString์€ Object.prototype์˜ ๋ฉ”์„œ๋“œ

๐Ÿ’ก Reflect.has ๋ฉ”์„œ๋“œ

ES6 ์—์„œ ๋„์ž…๋˜์—ˆ๊ณ , in ์—ฐ์‚ฐ์ž์™€ ๋™์ผํ•˜๊ฒŒ ๋™์ž‘.

const person = { name: 'Lee' };

console.log(Reflect.has(person, 'name')); // true
console.log(Reflect.has(person, 'toString)); // true

7-2. Object.prototype.hasOwnProperty ๋ฉ”์„œ๋“œ

Object.prototype.hasOwnProperty ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๊ฐ์ฒด์— ํŠน์ • ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ.

์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์€ ํ”„๋กœํผํ‹ฐ ํ‚ค๊ฐ€ ๊ฐ์ฒด ๊ณ ์œ ์˜ ํ”„๋กœํผํ‹ฐ ํ‚ค์ธ ๊ฒฝ์šฐ์—๋งŒ true๋ฅผ ๋ฐ˜ํ™˜ ์ƒ์†๋ฐ›์€ ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ ํ‚ค์ธ ๊ฒฝ์šฐ false๋ฅผ ๋ฐ˜ํ™˜.

console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('age')); // false
console.log(person.hasOwnProperty('toString')); // false

8. ํ”„๋กœํผํ‹ฐ ์—ด๊ฑฐ

8-1. for ... in ๋ฌธ

๊ฐ์ฒด์˜ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์—ด๊ฑฐํ•˜๋ ค๋ฉด for...in๋ฌธ์„ ์‚ฌ์šฉ.

for (๋ณ€์ˆ˜์„ ์–ธ๋ฌธ in ๊ฐ์ฒด) {...}
const person = {
  name: 'noh',
  address: 'Seouol'
};

// for...in ๋ฌธ์˜ ๋ณ€์ˆ˜ prop์— person ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ ํ‚ค๊ฐ€ ํ• ๋‹น๋œ๋‹ค.
for(const key in person) {
  console.log(key + ':' + person[key]);
}

// name: noh
// address: Seoul

for...in ๋ฌธ์€ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ ๊ฐœ์ˆ˜๋งŒ ํผ ์ˆœํšŒ ๋ณ€์ˆ˜ ์„ ์–ธ๋ฌธ์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜์— ํ”„๋กœํผํ‹ฐ ํ‚ค๋ฅผ ํ• ๋‹นํ•œ๋‹ค.

for...in ๋ฌธ์€ ์ƒ์†๋ฐ›์€ ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ๊นŒ์ง€ ์—ด๊ฑฐํ•œ๋‹ค.

const person = {
  name: "noh",
  address: "Seoul"
};

// in ์—ฐ์‚ฐ์ž๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์†๋ฐ›์€ ๋ชจ๋“  ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ™•์ธํ•œ๋‹ค.
console.log('toString' in person); // true

// for...in ๋ฌธ๋„ ๊ฐ์ฒด๊ฐ€ ์ƒ์†๋ณด๋‹ค์€ ๋ชจ๋“  ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์—ด๊ฑฐํ•œ๋‹ค.
// ํ•˜์ง€๋งŒ toString๊ณผ ๊ฐ™์€ Object.prototype์˜ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—ด๊ฑฐ๋˜์ง€ ์•Š๋Š”๋‹ค.
for(const key in person) {
  console.log(key + ':' + person[key])
}

// name: "noh"
// address: "Seoul"

toString ๋ฉ”์„œ๋“œ๊ฐ€ ์—ด๊ฑฐํ•  ์ˆ˜ ์—†๋„๋ก ์ •์˜๋˜์–ด ์žˆ๋Š” ํ”„๋กœํผํ‹ฐ์ด๊ธฐ ๋•Œ๋ฌธ ๋‹ค์‹œ ๋งํ•ด, Object.prototype.string ํ”„๋กœํผํ‹ฐ์˜ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ [[Enumerable]]์˜ ๊ฐ’์ด false์ด๊ธฐ ๋•Œ๋ฌธ.

for...in ๋ฌธ์€ ๊ฐ์ฒด์˜ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ ์ƒ์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ํ”„๋กœํ† ํƒ€์ž…์˜ ํ”„๋กœํผํ‹ฐ ์ค‘์—์„œ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ [[Emumerable]]์˜ ๊ฐ’์ด true์ธ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์—ด๊ฑฐํ•œ๋‹ค.

const person  = {
  name: 'noh',
  address: 'Seoul',
  __proto__: { age: 20}
};

for (const key in person) {
  console.log(key + ":" + person[key]);
}
// name: noh
// address: Seoul
// age: 20

for ... in ๋ฌธ์€ ํ”„๋กœํผํ‹ฐ ํ‚ค๊ฐ€ ์‹ฌ๋ฒŒ์ธ ํ”„๋กœํผํ‹ฐ๋Š” ์—ด๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค.

const sym = Symbol();
const obj = {
  a: 1,
  [sym]: 10
};

for (const key in obj) {
  console.log(key + ": " + obj[key]);
}
// a : 1

์ƒ์†๋ฐ›์€ ํ”„๋กœํผํ‹ฐ ์ œ์™ธ ๊ฐ์ฒด ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ๋งŒ ์—ด๊ฑฐํ•˜๋ ค๋ฉด Obejct.prototype.hasOwnproperty ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ์ธ์ง€ ํ™•์ธ.

const person  = {
  name: 'noh',
  address: 'Seoul',
  __proto__: { age: 20}
};

for (const key in personb) {
  // ๊ฐ์ฒด ์ž์‹ ์˜ ํ”„๋กœํผํ‹ฐ์ธ์ง€ ํ™•์ธ
  if(!person.hasOwnProperty(key)) contineu;
  console.log(key + ':' + person[pkey]);
}

// name: noh
// address : Seoul

๋ฐฐ์—ด์—๋Š” for...in๋ฌธ์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  for๋ฌธ for...of๋ฌธ ๋˜๋Š” Array.prototype.forEach ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅ. ์‚ฌ์‹ค ๋ฐฐ์—ด๋„ ๊ฐ์ฒด์ด๋ฏ€๋กœ ํ”„๋กœํผํ‹ฐ์™€ ์ƒ์†๋ฐ›์€ ํ”„๋กœํผํ‹ฐ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค.

const arr = [1, 2, 3];
arr.x = 10; // ๋ฐฐ์—ด๋„ ๊ฐ์ฒด์ด๋ฏ€๋กœ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

for (const i in arr) {
  // ํ”„๋กœํผํ‹ฐ x๋„ ์ถœ๋ ฅ๋œ๋‹ค.
  console.log(arr[i]); // 1 2 3 10
};

// arr.length๋Š” 3์ด๋‹ค.
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]); // 1 2 3
}

// forEach ๋ฉ”์„œ๋“œ๋Š” ์š”์†Œ๊ฐ€ ์•„๋‹Œ ํ”„๋กœํผํ‹ฐ๋Š” ์ œ์™ธํ•œ๋‹ค.
arr.forEach(v => console.log(v)); // 1 2 3

// for...of๋Š” ๋ณ€์ˆ˜ ์„ ์–ธ๋ฌธ์—์„œ ์„ ์–ธํ•œ ๋ณ€์ˆ˜์— ํ‚ค๊ฐ€ ์•„๋‹Œ ๊ฐ’์„ ํ• ๋‹นํ•œ๋‹ค.
for (const value of arr) {
  console.log(value); // 1 2 3
};

8-2. Object.keys / values / entries ๋ฉ”์„œ๋“œ

๊ฐ์ฒด ์ž์‹ ์˜ ๊ณ ์œ  ํ”„๋กœํผํ‹ฐ๋งŒ ์—ด๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” for ... in๋ฌธ์„ ์‚ฌ์šฉํ•œ ๊ฒƒ๋ณด๋‹ค Object.keys / values / entries ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

โœ” Object.keys

๊ฐ์ฒด ์ž์‹ ์˜ ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•œ ํ”„๋กœํผํ‹ฐ ํ‚ค๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

const person = {
  name: "noh",
  address: "Seoul",
  __proto__: { age: 20 }
};

console.log(Object.keys(person)); // {"name", "address"}

โœ” Object.values

ES8์—์„œ ๋„์ž…๋˜์—ˆ๊ณ  ๊ฐ์ฒด ์ž์‹ ์˜ ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜.

console.log(Object.values(person)); // ["noh", "Seoul"]

โœ” Object.entries

ES8์—์„œ ๋„์ž…๋˜์—ˆ๊ณ  ๊ฐ์ฒด ์ž์‹ ์˜ ์—ด๊ฑฐ ๊ฐ€๋Šฅํ•œ ํ”„๋กœํผํ‹ฐ ํ‚ค์™€ ๊ฐ’์˜ ์Œ์˜ ๋ฐฐ์—ด์„ ๋ฐฐ์—ด์— ๋‹ด์•„ ๋ฐ˜ํ™˜.

console.log(Object.entries(person)); // ["name", "noh"], ["address", "Seoul"]

Object.entries(person).forEach(([key, value]) => console.log(key, value));
/*
'name' 'noh'
'address' 'Seoul'
*/

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