[๐Ÿ“– ๋ชจ๋˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋”ฅ๋‹ค์ด๋ธŒ] 16์žฅ. ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ

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

JavaScript(Deep Dive)

๋ชฉ๋ก ๋ณด๊ธฐ
11/23

ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ

1. ๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ

๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์˜ ๊ตฌํ˜„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ECMAScript ์‚ฌ์–‘์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์˜์‚ฌ ํ”„๋กœํผํ‹ฐ์™€ ์˜์‚ฌ ๋ฉ”์„œ๋“œ๋‹ค. ECMAScript ์‚ฌ์–‘์— ๋“ฑ์žฅํ•˜๋Š” ์ด์ค‘ ๋Œ€๊ด„ํ˜ธ [[..]]๋กœ ๊ฐ์‹ผ ์ด๋ฆ„๋“ค์ด ๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋‹ค.

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

const o = {};

// ๋‚ด๋ถ€ ์Šฌ๋กฏ์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์˜ ๋‚ด๋ถ€ ๋กœ์ง์ด๋ฏ€๋กœ ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.
o.[[Prototype]] // Uncaught SyntaxError : Unexpected token '['
// ๋‹จ, ์ผ๋ถ€ ๋‚ด๋ถ€ ์Šฌ๋กฏ๊ณผ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ์— ํ•œํ•˜์—ฌ ๊ฐ„์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์„ ์ œ๊ณตํ•˜๊ธฐ๋Š” ํ•œ๋‹ค.
o.__proto__ // Object.prototype

2. ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์™€ ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ”„๋กœํผํ‹ฐ์˜ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ๊ธฐ๋ณธ๊ฐ’์„ ์ž๋™ ์ •์˜ํ•œ๋‹ค. ํ”„๋กœํผํ‹ฐ์˜ ์ƒํƒœ๋ž€ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’ ๊ฐ’์˜ ๊ฐฑ์‹  ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ์—ด๊ฑฐ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ์žฌ์ •์˜ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ๋งํ•œ๋‹ค.

ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ๊ด€๋ฆฌํ•˜๋Š” ๋‚ด๋ถ€ ์ƒํƒœ ๊ฐ’์ธ ๋‚ด๋ถ€ ์Šฌ๋กฏ [[Value]] [[Enumerable]] [[Configurable]]์ด๋‹ค. ๋”ฐ๋ผ์„œ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†์ง€๋งŒ Object.getOwnPropertyDescriptor ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„์ ‘์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜๋Š” ์žˆ๋‹ค.

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

ES8์—์„œ ๋„์ž…๋œ Object.getOwnPropertyDescriptor๋ฉ”์„œ๋“œ๋Š” ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ์˜ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด๋“ค์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

const person = {
	name : "Lee"
};

// ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
console.log(Object.getOwnPropertyDescriptor(person, 'name'));
// {value : "Lee", writable: true, enumerable: true, configurable: true}

// ํ”„๋กœํผํ‹ฐ ๋™์  ์ƒ์„ฑ
person.age = 20;

// ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ์˜ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด๋“ค์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
console.log(Object.getOwnPropertyDescriptor(person));
//{ name: {value : "Lee", writable: true, enumerable: true, configurable: true}
// age: {value : "20", writable: true, enumerable: true, configurable: true} }

3. ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ์™€ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ

ํ”„๋กœํผํ‹ฐ๋Š” ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ์™€ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

3-1. ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ

  • ํ‚ค์™€ ๊ฐ’์œผ๋กœ ๊ตฌ์„ฑ๋œ ์ผ๋ฐ˜์ ์ธ ํ”„๋กœํผํ‹ฐ๋‹ค. ์ง€๊ธˆ๊ฐ€์ง€ ์‚ดํŽด๋ณธ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋Š” ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๋‹ค.
const person = {
	name : "Lee"
};

// ํ”„๋กœํผํ‹ฐ ๋™์  ์ƒ์„ฑ
person.age = 20;

console.log(Object.getOwnPropertyDescriptor(person));
//{ name: {value : "Lee", writable: true, enumerable: true, configurable: true}
// age: {value : "20", writable: true, enumerable: true, configurable: true} }

Object.getOwnPropertyDescriptor๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด๋ฅผ ์‚ดํŽด๋ณด๋ฉด value์˜ ๊ฐ’์€ "Lee" ์ด๊ฒƒ์€ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ [[value]]์˜ ๊ฐ’์ด "Lee"์ธ ๊ฒƒ์„ ์˜๋ฏธ. ๊ทธ๋ฆฌ๊ณ  writable, enumerable, configurable ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์€ ๋ชจ๋‘ true๋‹ค. ์ด๊ฒƒ์€ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ [[Writable]] [[Enumerable]] [[Cinfigurable]]์˜ ๊ฐ’์ด ๋ชจ๋‘ true์ธ ๊ฒƒ์„ ์˜๋ฏธ

ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ [[value]]์˜ ๊ฐ’์€ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ์ดˆ๊ธฐํ™”๋˜๋ฉฐ [[Writable]] [[Enumerable]] [[Cinfigurable]]์˜ ๊ฐ’์€ true๋กœ ์ดˆ๊ธฐํ™”๋˜๋ฉฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋™์  ์ถ”๊ฐ€ํ•ด๋„ ๋งˆ์ฐฌ๊ฐ€์ง€

3-2. ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ

  • ์ž์ฒด์ ์œผ๋กœ๋Š” ๊ฐ’์„ ๊ฐ–์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ์ €์žฅํ•  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ์ ‘๊ทผ์ž ํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ๋œ ํ”„๋กœํผํ‹ฐ๋‹ค.
  • ์ ‘๊ทผ์ž ํ•จ์ˆ˜๋Š” getter/setterํ•จ์ˆ˜๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค. ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” getter์™€ setter ํ•จ์ˆ˜๋ฅผ ๋ชจ๋‘ ์ •์˜ํ•  ์ˆ˜๋„ ์žˆ๊ณ  ํ•˜๋‚˜๋งŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
const person = {
	// ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ
  	firstName : "Noh",
  	lastName: "YoungWan",
  
  	// fullName์€ ์ ‘๊ทผ์ž ํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ๋œ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋‹ค.
  	// getter ํ•จ์ˆ˜
  	get fullName() {
	return `${this.firstName} ${this.lastName}`'
    },
  	// setter ํ•จ์ˆ˜
  	set fullName(name) {
	[this.firstName, this.lastName] = name.split('');
    }
};
// ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•œ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์˜ ์ฐธ์กฐ
console.log(person.firstName + '' + person.lastName); // Noh YoungWan

// ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’์˜ ์ €์žฅ
// ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ fullName์— ๊ฐ’์„ ์ €์žฅํ•˜๋ฉด setter ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
person.fullName = "YoungWan Noh";
console.log(person); // {firstName: "YoungWan", lastName: "Noh"}

// ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’์˜ ์ฐธ์กฐ
// ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ fullName์— ์ ‘๊ทผํ•˜๋ฉด getter ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
console.log(person.fullName); // YoungWan Noh

// firstName์€ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๋‹ค 
// ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ๋Š” [[Value]], [[Writable]], [[Enumerable]],[[Configurable]]
// ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ๊ฐ–๋Š”๋‹ค 

// fullName์€ ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋‹ค.
// ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” [[Get

let descriptor = Object.getOwnPropertyDescriptor(person, 'firstName'); 
console.log(descriptor) 
// {get: f, set: f, enumerable: true, configurable: true}
  • ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ๋Š” ์ž์ฒด์ ์œผ๋กœ ๊ฐ’(ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ [[value]])์„ ๊ฐ€์ง€์ง€ ์•Š์œผ๋ฉฐ ๋‹ค๋งŒ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํŠธ์˜ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ์ €์žฅํ•  ๋•Œ ๊ด€์—ฐํ•  ๋ฟ์ด๋‹ค.

4. ํ”„๋กœํผํ‹ฐ ์ •์˜

ํ”„๋กœํผํ‹ฐ ์ •์˜๋ž€? ์ƒˆ๋กœ์šด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด์„œ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•˜๊ฑฐ๋‚˜, ๊ธฐ์กด ํ”„๋กœํผํ‹ฐ์˜ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์žฌ์ •์˜ ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

Object.defineProperty ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋กœํผํ‹ฐ์˜ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ธ์ˆ˜๋กœ๋Š” ๊ฐ์ฒด์˜ ์ฐธ์กฐ์™€ ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ์˜ ํ‚ค์ธ ๋ฌธ์ž์—ด, ํ”„๋กœํผํ‹ฐ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

const person = {};

// ๋ฐ์ดํ„ฐ ํ”„๋กœํผํ‹ฐ ์ •์˜
Object.defineProperty(person, 'firstName', {
	value: "Noh",
  	writable: true,
  	enumerable: true,
  	configurable: true
});

Object.defineProperty(person, 'lastName', {
	value: "YoungWan"
});

let descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log('firstName', descriptor)
// firstName {value: "Noh", writable: true, enumerable: true, configurable: true }
descriptor = Object.getOwnPropertyDescriptor(person, 'lastName');
// ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ˆ„๋ฝ์‹œํ‚ค๋ฉด undefined, false๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์ด๋‹ค.
cosole.log('lastName', descriptor)
// lastName {value: "YoungWan", writable: false, enumnerable: false, configurable: fasle }

// [[Enumerable]]์˜ ๊ฐ’์ด fasle์ธ ๊ฒฝ์šฐ
// ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๋Š” for..in ๋ฌธ์ด๋‚˜ object.keys๋“ฑ์œผ๋กœ ์—ด๊ฑฐํ•  ์ˆ˜ ์—†๋‹ค.
// lastName ํ”„๋กœํผํ‹ฐ๋Š” [[Emumerable]]์˜ ๊ฐ’์ด false์ด๋ฏ€๋กœ ์—ด๊ฑฐ๋˜์ง€ ์•Š๋Š”๋‹ค.
console.log(Object.keys(person)); // ["firstName"]

// [[Wirtable]]์˜ ๊ฐ’์ด false์ธ ๊ฒฝ์šฐ
// ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๋Š” [[Wirtable]]์˜ ๊ฐ’์ด false ์ด๋ฏ€๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.
// ์ด๋•Œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋ฉด ์—๋Ÿฌ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ๋ฌด์‹œ๋œ๋‹ค.
person.lastName = "Kim"

// [Configurable]]์˜ ๊ฐ’์ด false์ธ ๊ฒฝ์šฐ ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์—†๋‹ค.
// lastName ํ”„๋กœํผํ‹ฐ๋Š” [[Configurable]]์˜ ๊ฐ’์ด false์ด๋ฏ€๋กœ ์‚ญ์ œํ•  ์ˆ˜ ์—†๋‹ค.
// ์ด๋•Œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ญ์ œํ•˜๋ฉด ์—๋Ÿฌ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ๋ฌด์‹œ๋œ๋‹ค.
delete person.lastName;

// [Configurable]]์˜ ๊ฐ’์ด false์ธ ๊ฒฝ์šฐ ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†๋‹ค.
// Object.defineProperty(person, 'lastName', {enumerable: true});
// Uncaught TypeError: Cannot redefine property: lastName

๐Ÿ’ก Object.defineProperty ๋ฉ”์„œ๋“œ๋กœ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ •์˜ํ•  ๋•Œ ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ผ๋ถ€ ์ƒ๋žต ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํ”„๋กœํผํ‹ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ์ฒด์—์„œ ์ƒ๋žต๋œ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ธฐ๋ณธ๊ฐ’์ด ์ ์šฉ๋œ๋‹ค.

๐Ÿ’ก Object.defineProperty ๋ฉ”์„œ๋“œ๋Š” ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ ํ”„๋กœํผํ‹ฐ๋งŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. Object.defineProperties ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ํ•œ ๋ฒˆ์— ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค

const person = {};
Object.defineProperties(eprson, {
	firstName: {
	value: "Noh",
	writable: true,
	enumerable: true,
	configurable: true,
  },
  	lastName: {
	value: "YoungWan",
	writable: true,
	enumerable: true,
	configurable: true,
  },
  // ์ ‘๊ทผ์ž ํ”„๋กœํผํ‹ฐ ์ •์˜
  fullName: {
	// getter ํ•จ์ˆ˜
    get() {
		return `${this.firstName} ${this.lastName}`
    },
    // setter ํ•จ์ˆ˜
    set(name) {
	[this.firstName, this.lastName] = name.split(' ');
    },
    enumerable: true,
    configurable: true
  }
});
// set ์‚ดํ–‰
person.fullName = "YoungWan Noh";
console.log(person) // {firstName: YoungWan, lastName: Noh}

5. ๊ฐ์ฒด ๋ณ€๊ฒฝ ๋ฐฉ์ง€

๊ฐ์ฒด๋Š” ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์ด๋ฏ€๋กœ ์žฌํ• ๋‹น ์—†์ด ์ง์ ‘ ๋ณ€๊ฒฝ๊ฐ€๋Šฅ.

Object.defineProperty ๋˜๋Š” Object.defineProperties ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์žฌ์ •์˜ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ์ฒด์˜ ๋ณ€๊ฒฝ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณต, ๊ฐ์ฒด ๋ณ€๊ฒฝ ๋ฐฉ์ง€ ๋ฉ”์„œ๋“œ๋“ค์€ ๊ฐ์ฒด์˜ ๋ณ€๊ฒฝ์„ ๊ธˆ์ง€ํ•˜๋Š” ๊ฐ•๋„๊ฐ€ ๋‹ค๋ฅด๋‹ค.

5-1. ๊ฐ์ฒด ํ™•์žฅ ๊ธˆ์ง€

Object.preventExtensions ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์˜ ํ™•์žฅ์„ ๊ธˆ์ง€ํ•œ๋‹ค. ๊ฐ์ฒด์˜ ํ™•์žฅ ๊ธˆ์ง€๋ž€ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€ ๊ธˆ์ง€๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ํ™•์žฅ์ด ๊ธˆ์ง€๋œ ๊ฐ์ฒด๋Š” ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.

ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด์ธ์ง€ ์—ฌ๋ถ€๋Š” Object.isExtensible ๋ฉ”์„œ๋“œ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const person = { name: "noh"};

// person ๊ฐ์ฒด๋Š” ํ™•์žฅ์ด ๊ธˆ์ง€๋œ ๊ฐ์ฒด๊ฐ€ ์•ˆ๋œ๋‹ค.
console.log(Object.isExtensible(person)); // true

// person ๊ฐ์ฒด์˜ ํ™•์žฅ์„ ๊ธˆ์ง€ํ•˜์—ฌ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๋ฅผ ๊ธˆ์ง€ํ•œ๋‹ค.
Object.preventExtensions(person);

// person ๊ฐ์ฒด๋Š” ํ™•์žฅ์ด ๊ธˆ์ง€๋œ ๊ฐ์ฒด๋‹ค.
console.log(Object.isExtensible(person)); // false

// ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
person.age = 20; // ๋ฌด์‹œ. strict mode์—์„œ๋Š” ์—๋Ÿฌ
console.log(person); // {name: "noh"}

// ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๋Š” ๊ธˆ์ง€๋˜์ง€๋งŒ ์‚ญ์ œ๋Š” ๊ฐ€๋Šฅํ•˜๋‹ค.
delete person.name;
console.log(person); // {}

// ํ”„๋กœํผํ‹ฐ ์ •์˜์— ์˜ํ•œ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๋„ ๊ธˆ์ง€๋œ๋‹ค.
Object.defineProperty(person, 'age' { value: 20 });
// TypeError : Cannot define property age, Object is not extensible

5-2. ๊ฐ์ฒด ๋ฐ€๋ณธ

Object.seal ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ€๋ด‰ํ•œ๋‹ค. ๊ฐ์ฒด ๋ฐ€๋ด‰์ด๋ž€ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œ์™€ ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์žฌ์ •์˜ ๊ธˆ์ง€๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ๋ฐ€๋ด‰๋œ ๊ฐ์ฒด๋Š” ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฐ€๋ด‰๋œ ๊ฐ์ฒด์ธ์ง€ ์—ฌ๋ถ€๋Š” Object.isSealed ๋ฉ”์„œ๋“œ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const person = { name : "noh" };

// person ๊ฐ์ฒด๋Š” ๋ฐ€๋ด‰(seal)๋œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ค.
console.log(Object.isSealed(person)) // false

// person ๊ฐ์ฒด๋ฅผ ๋ฐ€๋ด‰(seal)ํ•˜์—ฌ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€, ์‚ญ์ œ, ์žฌ์ •์˜๋ฅผ ๊ธˆ์ง€ํ•œ๋‹ค.
Object.seal(person);

// person ๊ฐ์ฒด๋Š” ๋ฐ€๋ด‰(seal)๋œ ๊ฐ์ฒด๋‹ค.
console.log(Object.isSealed(person)) // true

// ๋ฐ€๋ด‰(seal)๋œ ๊ฐ์ฒด๋Š” configurable์ด false๋‹ค.
console.log(Object.getOwnPropertyDescriptors(person));
// name: { configurable: false }

// ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
person.age = 20; // ๋ฌด์‹œ strict mode์—์„œ๋Š” ์—๋Ÿฌ
console.log(person); // { name: "noh" }

// ํ”„๋กœํผํ‹ฐ ์‚ญ์ œ๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
delete person.name; // ๋ฌด์‹œ strict mode์—์„œ๋Š” ์—๋Ÿฌ
console.log(person); // { name: "noh" }

// ํ”„๋กœํผํ‹ฐ ๊ฐ’ ๊ฐฑ์‹ ์€ ๊ฐ€๋Šฅํ•˜๋‹ค.
person.name = "Noh";
console.log(person); // { name: "Noh" }

// ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์žฌ์ •์˜๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
Object.defineProperty(person, 'name', {configurable: true});
// TypeError: Cannot redefine property: name

5.3 ๊ฐ์ฒด ๋™๊ฒฐ

Object.freeze ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ๋™๊ฒฐํ•œ๋‹ค. ๊ฐ์ฒด ๋™๊ฒฐ์ด๋ž€ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œ์™€ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์žฌ์ •์˜ ๊ธˆ์ง€, ํ”„๋กœํผํ‹ฐ ๊ฐ’ ๊ฐฑ์‹  ๊ธˆ์ง€๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ฆ‰, ๋™๊ฒฐ๋œ ๊ฐ์ฒด๋Š” ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋™๊ฒฐ๋œ ๊ฐ์ฒด์ธ์ง€ ์—ฌ๋ถ€๋Š” Object.isFronzen ๋ฉ”์„œ๋“œ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const person = { name : "noh" };

// person ๊ฐ์ฒด๋Š” ๋™๊ฒฐ(freeze)๋œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋‹ค.
console.log(Object.isFrozen(person)); // false

// person ๊ฐ์ฒด๋ฅผ ๋™๊ฒฐ(freeze)ํ•˜์—ฌ ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€, ์‚ญ์ œ, ์žฌ์ •์˜ ์“ฐ๊ธฐ๋ฅผ ๊ธˆ์ง€ํ•œ๋‹ค.
Object.freeze(person);

// person ๊ฐ์ฒด๋Š” ๋™๊ฒฐ(freeze)๋œ ๊ฐ์ฒด๋‹ค.
console.log(Object.isFrozen(person)) // true

// ๋™๊ฒฐ(freeze)๋œ ๊ฐ์ฒด๋Š” writable๊ณผ configurable์ด false๋‹ค.
console.log(Object.getOwnPropertyDescriptors(person));
/*
{
	name: {value: "noh", writable: false, enumerable: true, configurable: false},
}
*/

// ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
persona.age = 20; // ๋ฌด์‹œ. strict mode์—์„œ๋Š” ์—๋Ÿฌ
console.log(person); // {name: "noh"}

// ํ”„๋กœํผํ‹ฐ ์‚ญ์ œ๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
delete person.name;  // ๋ฌด์‹œ. strict mode์—์„œ๋Š” ์—๋Ÿฌ
console.log(person) // {name: "noh"}

// ํ”„๋กœํผํ‹ฐ ๊ฐ’ ๊ฐฑ์‹ ์ด ๊ธˆ์ง€๋œ๋‹ค.
person.name = "Noh";
console.log(person) // {name: "noh"}

// ํ”„๋กœํผํ‹ฐ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์žฌ์ •์˜๊ฐ€ ๊ธˆ์ง€๋œ๋‹ค.
Object.defineProperty(person, 'name', { configurable: true });
//TypeError: Cannot redefine property: name

5-4. ๋ถˆ๋ณ€ ๊ฐ์ฒด

์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ๋ณ€๊ฒฝ ๋ฐฉ์ง€ ๋ฉ”์„œ๋“œ๋“ค์€ ์–•์€ ๋ณ€๊ฒฝ ๋ฐฉ์ง€๋กœ ์ง์† ํ”„๋กœํผํ‹ฐ๋งŒ ๋ณ€๊ฒฝ์ด ๋ฐฉ์ง€๋˜๊ณ  ์ค‘์ฒฉ ๊ฐ์ฒด๊นŒ์ง€๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€๋Š” ๋ชปํ•œ๋‹ค. ๋”ฐ๋ผ์„œ Object.freeze ๋ฉ”์„œ๋“œ๋กœ ๊ฐ์ฒด๋ฅผ ๋™๊ฒฐํ•˜์—ฌ๋„ ์ค‘์ฒฉ ๊ฐ์ฒด๊นŒ์ง€ ๋™๊ฒฐํ•  ์ˆ˜ ์—†๋‹ค.

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

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