Photo by Greg Rakozy on Unsplash
JavaScript Object ์ ๋ํ ์ ๋ฐ์ ์ธ ๋ด์ฉ์ ๋ค๋ฃน๋๋ค
์ด ๊ธ์ ์๋ ์ฑ ๊ณผ ๋ด์ฉ์ ์ฐธ๊ณ ํ์์ต๋๋ค
(์ด ๊ธ์ Notion ์ฑ ์ผ๋ก ์์ฑํ ์น ํ์ด์ง์์๋ ๋ณผ ์ ์์ต๋๋ค! ๋ด์ฉ์ ๋์ผํฉ๋๋ค)
๊ฐ์ฒด์ ์์ฑํ๋ ์ธ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค
new Object()
Object.create()
{}
์ฐ๋ฆฌ๊ฐ ํํ ์ฌ์ฉํ๋ย {}
ย ๋ Object literal ์ด๋ผ๊ณ ํฉ๋๋ค
๊ทธ๋ฆฌ๊ณ ํน๋ณํ ์ด์ ๊ฐ ์๋ค๋ฉด Object literal ์ธ์ ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ง์ํฉ๋๋ค
๊ทธ ์ด์ ๋...
1. Property ์ถ๊ฐ๊ฐ ์ด๋ ต์ต๋๋ค
// Object๋ฅผ ์์ฑํ๊ณ , ํ๋์ฉ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํด๋๊ฐ์ผ ํฉ๋๋ค
const Square = new Object();
Square.width = 300;
Square.height = 300;
// ๋ง์ฝ ์๋์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ํ ์ ์๋ค๊ณ ํ์๋ฉด... ๊ทธ๋ฅ Object literal ์ด ๋ซ์ง ์์๊น์?
const Rectangle = new Object();
Object.assign(Rectangle, { width: 300, height: 300 });
2. Object literal ํ๊ธฐ๋ฒ์ด ์ฝ๋ ๊ณต๊ฐ์ ๋ ์ฐจ์ง ํฉ๋๋ค
3. ๋ณดํธ์ ์ธ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ฐ๋ฅด๋ ๊ฒ์ด ์ข์ต๋๋ค
์ฐ๋ฆฌ๋ ํ์ฐ์ ์ผ๋ก ํ์
์ ํด์ผํ๊ธฐ ๋๋ฌธ์
๋๋ค
๊ทธ๋ฆฌ๊ณ , ์ฑ๋ฅ ์ฐจ์ด๊ฐ ์๋ค๋ ๊ธ์ ์ฝ์ ์ ์ด ์๋๋ฐ
Chrome 72 ๋ฒ์ ๊ธฐ์ค์ ๊ฐ๋จํ ํ
์คํธ์์๋ ํฐ ์ฐจ์ด๊ฐ ์๋๊ฒ์ผ๋ก ํ์ธ๋ฉ๋๋ค
1. ์์(Primitive) ๊ฐ์ ์ ์ธํ ๋ค๋ฅธ ๋ด์ฅ ๊ฐ์ฒด๋ Object ์ ํ์ ์งํฉ์ ๋๋ค
Primitives (์ฐ๋ฆฌ๋ Object์ ํ์ ์งํฉ์ด ์๋์์!)
2. ๋ด์ฅ ๊ฐ์ฒด๋ ๊ฝค ๋ง๊ธฐ ๋๋ฌธ์ ๋งํฌ๋ก ๋์ฒดํฉ๋๋ค
๋ํ์ ์ผ๋ก Function
, Array
๋ํ object
์ ํ์ ์งํฉ ์
๋๋ค
function test () {}; test.a = '์ค์';
๊ฐ์ด ํจ์์ ํ๋กํผํฐ ์ถ๊ฐ๊ฐ ๋๋๊ฑด ๋ค๋ค ์์คํ
๋ฐ์
์ด๋ ๊ฒ ํ ์ ์๋๊ฑด Function
์ด object
์ ํ์ ์งํฉ์ด๊ธฐ ๋๋ฌธ์
๋๋ค
3. ๋ด์ฅ ๊ฐ์ฒด ์์ฑ์๋ก ์์ฑํ ๊ฐ์ ์์๊ฐ๊ณผ ํ์ ์ด ๋ค๋ฆ ๋๋ค
// string literal ๋ก ์์ ๋ฌธ์์ด ์์ฑ
const primitiveString = 'I am string';
typeof primitiveString // "string"
// String ์ด๋ผ๋ ๋ด์ฅ ๊ฐ์ฒด์ ์ธ์คํด์ค๊ฐ ์๋
primitiveString instanceof String; // false
const stringObject = new String('I am string');
typeof stringObject; // "object"
stringObject instanceof String; // true
// ๊ฐ์ฒด ํ์ ํ์
ํ์ธ
Object.prototype.toString.call(stringObject); // [object String]
4. object vs Object
Object ๋ object ์ constructor ์
๋๋ค
5. ๋ฒ์ธ, typeof null ์ ์ object ์ผ๊น?
typeof null === "object"
๋ผ๋๊ฑด ๋ค๋ค ์๊ณ ๊ณ์๋ ์ฌ์ค์
๋๋ค ๐
๊ทผ๋ฐ ์ null ์ object ํ์
์ทจ๊ธ์ ๋ฐ๊ฒ ๋์์๊น์? ๐ค
๊ฐ๋จํ ์ดํดํ ๋ฐ๋ฅผ ์ ํด๋๋ฆฌ๋ฉด (์ด ๊ธ์ ์ฝ์์ต๋๋ค!)
์๋ฐ์คํฌ๋ฆฝํธ ์ด๊ธฐ ์ธ์ด ์ค๊ณ ๋จ๊ณ์์ ๊ฐ์
์์ type tag(1~3 ๋นํธ)์ ์ค์ ๊ฐ์ผ๋ก ๊ตฌ์ฑ๋ 32๋นํธ ๋จ์๋ก ์ ์ฅ๋๋๋ฐ
์ด type tag ๋ ์๋ฃํ๋ณ๋ก ๋ฏธ๋ฆฌ ์ง์ ๋์ด ์์์ต๋๋ค
(object: 000, int: 1, double: 010, string: 100, boolean: 110)
null ์ ๋ณดํธ์ ์ผ๋ก ์๋ฌด๊ฒ๋ ์์์ ์๋ฏธํ๊ธฐ ๋๋ฌธ์
object ์ ์๋ฌด๊ฒ๋ ์์ (0) ์ด ๋ํด์ ธ
๋ง์น object ํ์
์ธ ๊ฒ ์ฒ๋ผ ์ ์ฅ๋ฉ๋๋ค ๐ฉ
(์๋ชป ์ดํดํ ๋ถ๋ถ์ด ์์ผ๋ฉด ๊ผญ ๋๊ธ ๋จ๊ฒจ์ฃผ์ธ์!)
๊ทธ๋ฆฌ๊ณ , null type check ๋ฅผ ์ํ ์ฝ๋ typeof null === "object"
์ ํ์ ํธํ์ ๋ง์ถ๊ธฐ ์ํด
typeof null === 'null'
๋ก ๋ณ๊ฒฝํ์๋ ์ ์์ ๊ฑฐ์ ๋์์ต๋๋ค
์๋ฐ์คํฌ๋ฆฝํธ๋ ๊ฐ์ฒด ๊ธฐ๋ฐ ํจ๋ฌ๋ค์ ์์์ ์ค๊ณ ๋์์ต๋๋ค
JavaScript is designed on a simple object-based paradigm.
**ํ๋์ ๊ฐ์ฒด๋ ํ๋กํผํฐ์ ์งํฉ์ด๋ฉฐ**, ํ๋์ ํ๋กํผํฐ๋ ์ด๋ฆ๊ณผ ๊ฐ์ ์ฐ๊ด์ฑ(๊ด๊ณ) ์
๋๋ค
An object is a **collection of properties**, and a property is an association between a name (or key) and a value.
๊ฐ์ฒด์ ํ๋กํผํฐ ์ด๋ฆ์ ๊ฐ์ ์ ๊ทผํ๊ธฐ ์ํ ๋ ํผ๋ฐ์ค ์ญํ ์ ํฉ๋๋ค
ํ๋กํผํฐ๋ช
์ ๊ฐ์ฒด ์ปจํ
์ด๋ ๋ผ๋ ๊ณณ์ ๋ณด๊ด๋์ด ์๋๋ฐ
์ด ํ๋กํผํฐ๋ช
์ ํตํด, ํ๋กํผํฐ ๊ฐ์ด ์ ์ฅ๋ ํฌ์ธํฐ๋ฅผ ํ์ฉํ์ฌ ๊ฐ์ ์ฐธ์กฐํ ์ ์์ต๋๋ค
(๊ฐ์ฒด ์ปจํ
์ด๋๋ Host ํ๊ฒฝ (๋ธ๋ผ์ฐ์ ) ์ ๋ฐ๋ผ ๊ทธ ๋์ ๋ฐฉ์์ด ๋ค๋ฆ
๋๋ค)
Property Name ์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง๊ฐ ์์ต๋๋ค
1. .
์ฐ์ฐ์
2. [ ]
์ฐ์ฐ์
const a = {}; a['Awesome-Property!'] = 1;
๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋คconst obj = {};
obj[null] = 'NULL'
obj[true] = 'TRUE'
obj[obj] = 'Object'
console.log(obj['null']) // 'NULL'
console.log(obj['true']) // 'TRUE'
console.log(obj['[object Object]']) // 'Object'
3. ๊ณ์ฐ๋ ํ๋กํผํฐ๋ช (Computed property name)
[ ]
๋ก ๊ฐ์ผ ๋ค ๊ณ์ฐ๋ ํ๋กํผํฐ๋ช
์ ์ฌ์ฉํ ์ ์๋คconst meow = 'MEOW';
const obj = {
[meow]: 'NYAN',
[meow+meow]: 'NYAN NYAN',
};
console.log(obj['MEOW']) // 'NYAN'
console.log(obj['MEOWMEOW']) // 'NYANNYAN'
// ES6 Symbol ์์๋ ์ฌ์ฉ๋จ
const objWithSymbol = {
[Symbol.Private]: "Private"
};
console.log(objWithSymbol[Symbol.Private]) // "Private"
์๋ฐ์คํฌ๋ฆฝํธ์์ ํ์ฉ๋๋ ๊ฐ์ ๋ชจ๋ ํ๋กํผํฐ์ ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค
ํํ Property Descriptor ๋ผ๊ณ ๋ถ๋ฅด๋
ํ๋กํผํฐ์ ํน์ฑ์ ๋ํ ์์ ์๋ ES5 ์ด์ ์๋ ํ์ธํ ์ ์์์ต๋๋ค
ํ์ฌ๋ descriptor ์ ๊ฐ์ ์กฐํํ๊ณ , ์์ ํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค
๊ทธ๋ฆฌ๊ณ , object ์ ๋ชจ๋ property ๋
๋ค ๊ฐ์ง์ Data Descriptor ์ ๋ ๊ฐ์ง์ Accessor Descriptor ์์ฑ์ ๊ฐ์ต๋๋ค
์ด๋ ๊ฒ ํ์ธํ ์ ์์ต๋๋ค!
const obj = { a: 1 };
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// console.log
// {value:1, writable: true, enumerable: true, configurable: true}
๊ทธ๋ผ, ๋จผ์ Data Descriptor ์ ๋ํด ์์ ๋ณด๊ฒ ์ต๋๋ค
1. value
ํ๋กํผํฐ์ ๊ฐ์ ์ ์ ํฉ๋๋ค
์๋ฐ์คํฌ๋ฆฝํธ์์ ํ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๊ฐ์ ํ ๋นํ ์ ์์ต๋๋ค
2. writable
ํ๋กํผํฐ ๊ฐ์ ์์ ๊ฐ๋ฅ ์ฌ๋ถ์ ๋ํด ์ ์ ํฉ๋๋ค
๋ง์ฝ writable: false
์ธ ๊ฒฝ์ฐ์๋ ์๋ ๋ ๊ฐ์ง ์กฐ๊ฑด ํ์์ ๋ค๋ฅด๊ฒ ๋์ํฉ๋๋ค
throw Error
const cat = {};
Object.defineProperty(cat, 'name', {
value: 'DoonDoon',
writable: false, // ํ ๋ฒ ์ ํ ์ด๋ฆ์ ๋ฐ๊ฟ ์ ์์ด์!
configurable: true,
enumerable: true,
});
cat.name = 'TT'; // ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค (์กฐ์ฉํ ์คํจ๐คซ)
console.log(cat.name) // DoonDoon
3. enumerable
ํ๋กํผํฐ ์ด๊ฑฐ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ์ ์ ํฉ๋๋ค
๊ฐ์ฒด ํ๋กํผํฐ๋ฅผ ์ด๊ฑฐํ๋ for ... in
๋ฌธ์ด๋,
Object.keys()
, Object.values()
, Object.entries()
๋ฑ์ ํจ์์์
ํ๋กํผํฐ๊ฐ ์ด๊ฑฐ๋์ง ์๋๋ก ์ ์ํ ์ ์์ต๋๋ค
const cat = {}
Object.defineProperties(cat, {
name: {
value: 'DoonDoon',
writable: true,
configurable: true,
enumerable: true,
},
age: {
value: 3,
writable: true,
configurable: true,
enumerable: false, // ๋์ด๋ ์๋ฆฌ๊ณ ์ถ์ง ์์์ ๐ฑ
},
});
for (let key in cat) { console.log(key) } // name
Object.keys(cat) // ["name"]
Object.values(cat) // ["DoonDoon"]
Object.entries(cat) // [["name", "DoonDoon"]]
4. configurable
Property Descriptor ์ ์์ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ์ ์ ํฉ๋๋ค
๋ง์ฝ false
์ผ ๊ฒฝ์ฐ์๋ writable: true
๋ฅผ writable: false
๋ก ๋ณ๊ฒฝํ๋ ๊ฒ ์ธ์
๋ชจ๋ ์ค์ ๋ณ๊ฒฝ์ด ๊ธ์ง๋ฉ๋๋ค (writable์ด ์ต์ด์ true ์๋ค๋ ์ ์ ํ์์)
๊ทธ๋ฆฌ๊ณ writable
๋ํ ํ ๋ฒ false
๋ก ๋ณ๊ฒฝ๋ ๋ค์๋ ๋ ์ด์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค!
๋ํ, ํ๋กํผํฐ๋ฅผ ์ญ์ ํ๋ ๊ฒ ๊น์ง๋ ๋ถ๊ฐ๋ฅ ํฉ๋๋ค.
ํ ๋ง๋๋ก,ย configurable: falseย ๋ ๋์์ฌ ์ ์๋ ๊ฐ์ ๊ฑด๋๋ ์
์
๋๋ค ๐ถ
const cat = {};
Object.defineProperties(cat, {
name: {
value: 'DoonDoon',
writable: true,
enumerable: true,
configurable: false, // name ํ๋กํผํฐ์ ๋ํ ์ค์ ์ ๋ ์ด์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค
},
age: {
value: 3,
writable: true,
enumerable: true,
configurable: true,
},
});
// writable ์ false ์์ true ๋ก ํ ๋ฒ๋ง ๋ณ๊ฒฝ ๊ฐ๋ฅํฉ๋๋ค. ๋์์ฌ ์ ์๋ ๊ฐ์ ๊ฑด๋๋ ๊ฑฐ์ฃ ๐ถ
Object.defineProperty(cat, 'name', { writable: false, });
try {
Object.defineProperty(cat, 'name', { writable: true, }); // ์ ๋ฐ๋๋ค! ๊ทธ๋ฆฌ๊ณ ์๋ฌ๊ฐ ๋ฐ์ ํฉ๋๋ค
} catch (e) {
console.error(e); // [TypeError: Cannot redefine property: name]
}
delete cat.name // ์ ์ง์์ ธ!
console.log(cat.name) // "DoonDoon"
console.log(Object.getOwnPropertyDescriptor(cat, 'name')); // { value: 'DoonDoon', writable: false, enumerable: true, configurable: false }
ํ๋กํผํฐ๊ฐ [Getter] || [Setter] ๊ฐ ๋ ์ ์๊ฒ ์ ์ํ ๊ฒ์ ์ ๊ทผ ์์ ์๋ผ๊ณ ํฉ๋๋ค
์ ๊ทผ ์์ ์๋ 4 ๊ฐ์ง์ ์์ฑ์ ๊ฐ์ต๋๋ค: configurable
, enumerable
, get
, set
(๊ฐ์ ๊ด๋ จ๋ ์์ฑ์ธ value
, writable
์์ฑ์ ๋ฌด์๋ฉ๋๋ค)
[Getter] / [Setter] ๋ฅผ ์ธ์ ์ฐ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ฅ๋จ์ ์ ๋ฌด์์ธ์ง์ ๋ํ ๋
ผ์๋
์ข์ ๊ธ๋ค๋ก ๋์ ํ๊ฒ ์ต๋๋ค ๐
1. [Getter]
ํ๋กํผํฐ๋ฅผ ํธ์ถํ ๋ ์คํ๋ ํจ์๋ก ๋ฐ์ธ๋ฉ ํฉ๋๋ค
์ผ๋ฐ์ ์ผ๋ก ์ด๋ ํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
๋ณดํต์ ๊ณ์ฐ๋ ๊ฐ์ ๋ฐํํด์ผ ํ๊ฑฐ๋,
๋ด๋ถ ๋ณ์(ํ๋)๋ฅผ ์ง์ ๋
ธ์ถํ๊ณ ์ถ์ง ์์๋ ์ฌ์ฉํ์ง๋ง
์๋ฐ์คํฌ๋ฆฝํธ๋ accessor ๊ฐ ์กด์ฌํ๊ธฐ ์๊ธฐ ๋๋ฌธ์
์ฐ์ ์ ๊ณ์ฐ๋ ๊ฐ์ ๋ฐํํ ๋ ์ฌ์ฉํ๋ค๊ณ ์๊ฐํ๋๊ฒ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค ๐ค
[Getter] ๋ ์๋์ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค
const cat = {
_name: 'DoonDoony',
get name() {
return `${this._name} the Cat`
},
}
// ํ๋กํผํฐ ์ ๊ทผ์ ํด๋, ์ ์๋ ํจ์๊ฐ ํธ์ถ๋๊ณ ๊ฐ์ด ๋ฐํ๋ฉ๋๋ค
console.log(cat.name) // 'DoonDoony the Cat'
[Getter] ๋ ์ด๋ฐ ํน์ง๋ค์ด ์์ต๋๋ค!
1. delete ์ฐ์ฐ์๋ฅผ ์ด์ฉํด ์ญ์ ๊ฐ ๊ฐ๋ฅํฉ๋๋ค
const obj = { get name() { return 'DoonDoony' } };
console.log(obj.name); // "DoonDoony"
delete obj.name;
console.log(obj.name); // undefined
2. defineProperty ๋ฅผ ์ด์ฉํด ๊ฐ์ฒด์ ์ ํ๋กํผํฐ๋ก ์ถ๊ฐ๊ฐ ๊ฐ๋ฅํฉ๋๋ค
const obj = { _name: 'DoonDoony' }
Object.defineProperty(obj, 'name', {
get: function() {
return `${this._name} the Cat!`
},
enumerable: true,
configurable: true,
})
console.log(obj.name) // "DoonDoony the Cat!"
3. ๊ณ์ฐ๋ ํ๋กํผํฐ(Computed Property) ์ด๋ฆ์ ์ฌ์ฉํ ์ ์์ต๋๋ค
const prefix = 'name'
const obj = {
get [prefix] () {
return 'Getter is called with prefix'
}
}
// prefix์ ๊ฐ์ ๋ฌธ์์ด์ธ "name" ํ๋กํผํฐ๋ช
์ผ๋ก ํธ์ถํ ์ ์์ต๋๋ค
console.log(obj.name) // "Getter is called with prefix"
4. lazy evaluation ์ด ๊ฐ๋ฅ ํฉ๋๋ค
[Getter] ๋ ํ๋กํผํฐ์ ์ ๊ทผํ๊ธฐ ์ ๊น์ง๋ ๊ฐ์ ๊ณ์ฐํ์ง ์์ต๋๋ค
๊ฐ์ด ์๋ [Getter]
๋ก ํ๊ฐ๋ฉ๋๋ค!
5. [Getter] ๋ฐํ๊ฐ์ ์บ์ฑ์ด ๊ฐ๋ฅํฉ๋๋ค
[Getter] ๊ฐ ํธ์ถ ์ ๊น์ง ํ๊ฐ๋์ง ์๋ ํน์ง๊ณผ
์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ณ์์ ๋ด๋ ๊ฐ์ ํ ๋ฒ๋ง ๊ณ์ฐ๋๋ค๋ ์ ์ ํ์ฉํ์ฌ
[Getter] ๋ฅผ ๊ฐ์ผ๋ก ํ๊ฐํด caching ํ ์ ์์ต๋๋ค
์ผ๋ฐ์ ์ธ ํค - ๋ฐธ๋ฅ ํํ์ ํ๋กํผํฐ๊ฐ ์๋๋ผ
[Getter] ๋ก ๊ตฌํํ๋ ์ด์ ๋ ์ง์ฐํ๊ฐ๋ฅผ ํ์ฉํ๋ ๊ฑด๋ฐ์
MDN ๋ฌธ์์์๋ ์๋์ ๊ฐ์ ๊ฒฝ์ฐ์ ์ ์ฉํ๋ค๊ณ ํฉ๋๋ค
์ฝ๋๋ฅผ ํ ๋ฒ ๋ณด๊ฒ ์ต๋๋ค ๐
const cat = {
get name() {
delete this.name; // 1
return this.name = 'DoonDoony๐'; // 2
}
}
console.log(cat.name); // 3
cat.name
์ด๋ผ๋ [Getter] ๋ฅผ cat ๊ฐ์ฒด์์ ์ ๊ฑฐํฉ๋๋คcat
๊ฐ์ฒด์ name
ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํฉ๋๋ค (name ์ ์ด ๋ ๋ถํฐ๋ [Getter] ๊ฐ ์๋๋๋ค)cat.name
[Getter] (์์ง์ [Getter]) ๊ฐ ํธ์ถ๋๊ณ , cat.name
ํ๋กํผํฐ๋ก ๋ณ๊ฒฝ ๋์ด ๊ฐ์ ๋ฐํํฉ๋๋ค๋ฐํ๊ฐ์ด this.name = 'DoonDoony๐'
์ ๊ฐ์ด ํ ๋น๋ฌธ(Assignment) ์์๋
์ ์์ ์ผ๋ก 'DoonDoony' ๋ผ๋ ๋ฌธ์์ด์ ๋ฐํํ๋ ์ด์ ๋
์๋ฐ์คํฌ๋ฆฝํธ์์ ํ ๋น๋ฌธ์ ํ ๋นํ ๊ฐ์ ๋ฐํํ๊ธฐ ๋๋ฌธ์
๋๋ค
(๋จ, var
, let
, const
ํค์๋ ์์ด ํ ๋นํ ๊ฒฝ์ฐ)
์์ ์์ ๋ ๋จ์ํ ๋ฌธ์์ด์ ๋ฐํํ๋ ์์ ๋ผ ์ค์ฉ์ ์ด์ง ์์ ๋ณด์ด์ง๋ง
์ค์ ๋ก ๊ต์ฅํ ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ณ์ฐ์ด ํ์ํ๋ฐ, ์ฝ๋ ์คํ ์์ ์ ๋ฏธ๋ฆฌ ๊ณ์ฐํด๋ ํ์๊ฐ ์๋ค๋ฉด
์ด์ ๊ฐ์ ๋ฐฉ๋ฒ์ด ์ ์ฉํ ๊ฒ ๊ฐ์ต๋๋ค.
์กฐ๊ธ์ ๊ทธ๋ด์ธํด ๋ณด์ด๋ ์์ ์ฝ๋ ์ ๋๋ค
// ์ฝ๋๋ ๋ณต์ฌํด์ ๋ธ๋ผ์ฐ์ ์ฝ์์ฐฝ์์ ์คํ ๊ฐ๋ฅํฉ๋๋ค
// Required only nodejs
// const { performance } = require('perf_hooks');
const obj = {
get memoizedGetter() {
delete this.memoizedGetter;
return this.memoizedGetter = [...Array(5e+7).keys()].reduce((prev, num) => prev + num, 0);
},
get commonGetter() {
return [...Array(5e+7).keys()].reduce((prev, num) => prev + num, 0);
},
};
const measureExecutionTime = (functionName, fn) => {
const start = performance.now();
fn();
return `[${functionName}] Elasped Time: ${performance.now() - start} ms`;
};
console.log(measureExecutionTime('Memoized Getter Test1', () => obj.memoizedGetter));
console.log(measureExecutionTime('Memoized Getter Test2', () => obj.memoizedGetter));
console.log(measureExecutionTime('Memoized Getter Test3', () => obj.memoizedGetter));
console.log(measureExecutionTime('Common Getter Test1', () => obj.commonGetter));
console.log(measureExecutionTime('Common Getter Test2', () => obj.commonGetter));
console.log(measureExecutionTime('Common Getter Test3', () => obj.commonGetter));
์ฝ๋๋ฅผ ์คํํ ๊ฒฐ๊ณผ์
๋๋ค
์ด์ ์กฐ๊ธ ๊ด์ฐฎ์ ๋ณด์ด์๋์? (์๋์๋ผ๋ฉด ์ด์ฉ ์ ์์ง๋ง ๐ญ)
๊ทผ๋ฐ ๋ฌธ๋ ์ด๋ฐ ์๊ฐ์ด ๋ญ๋๋ค!
[Getter] ๋ฅผ ์ผ๋ฐ์ ์ธ ํ๋กํผํฐ๋ก ๋ณ๊ฒฝํด๋ฒ๋ฆฌ๋ฉด, ๋ฎ์ด ์ธ ์ ์์ง ์์๊น?
์์์ฒ๋ผ ์ฌ์ฉํ๊ณ ์ถ์๋ฐ...๐ค
์ค์ ๋ก ์๋์ฒ๋ผ Property Descriptor ๋ฅผ ํ์ธํด๋ณด๋ฉด
์คํ ์ ํ ํ๋กํผํฐ์ ์ฑ๊ฒฉ์ด ์์ ํ ๋ค๋ฅธ๊ฒ์ ์ ์ ์์ต๋๋ค
(๊ทธ๋ฆฌ๊ณ ์ ๊ฐ์ด ํ ๋น ๋ฉ๋๋ค)
const cat = {
get name () {
// ์ญ์ ์ ์๋ getter ์ Property Descriptor ์์ฑ ๊ฐ์ด ํ์ธ๋ฉ๋๋ค
console.log(Object.getOwnPropertyDescriptor(this, 'name')); // { get: [Getter], set: undefined, enumerable: true, configurable: true }
delete this.name;
return this.name = 'DoonDoony';
}
};
console.log(cat.name); // "DoonDoony"
// getter ๋ฅผ ํธ์ถํ๋ฉด, ํ๋กํผํฐ๊ฐ ์ง์์ง๊ณ , ์ผ๋ฐ์ ์ธ ๊ฐ ํ๋กํผํฐ์ ์์ฑ์ด ํ์ธ๋ฉ๋๋ค.
console.log(Object.getOwnPropertyDescriptor(cat, 'name')); // { value: 'DoonDoony', writable: true, enumerable: true, configurable: true }
cat.name = 'TT'
console.log(cat.name) // "TT", ์ด๋ฐ! ๋๋๋๊ฐ ํฐํฐ๋ก ๋ณํ์ด์ ๐
๊ทธ๋ผ [Getter] ์ ์ง์ฐ ํ๊ฐ์ ์ฅ์ ์ ์ด๋ฆฌ๋ฉด์
๊ฐ์ ์์์ฒ๋ผ ๋ณํ์ง ์๊ฒ ์ ์งํ๋ ค๋ฉด ์ด๋ป๊ฒ ํ ์ ์์๊น์?
const obj = {
get hugeValue () {
console.log(Object.getOwnPropertyDescriptor(this, 'hugeValue')); // {get: [Getter], set: undefined, enumerable: true, configurable: true}
delete this.hugeValue;
const cachedValue = [...Array(5e+7).keys()].reduce((prev, curr) => prev + curr, 0);
return Object.defineProperty(this, 'hugeValue', {
value: cachedValue,
writable: false,
configurable: false,
enumerable: true,
}).hugeValue
},
name: 'HugeValueInside',
};
console.log(obj.hugeValue); // 1249999975000000
obj.hugeValue = '๋ณํด๋ผ ์!';
console.log(obj.hugeValue); // 1249999975000000
console.log(Object.getOwnPropertyDescriptor(obj, 'hugeValue')); // {value: 1249999975000000, writable: false, enumerable: true, configurable: false}
์บ์ฑํด์ผํ ํฐ ๊ฐ์ ๋ณ์์ ๋ด๊ณ , ๋ฐํ ์์ ์ ์์ ๊ฐ์ด ์ ์ํ๋ฉด ๋ฉ๋๋ค!
obj.hugeValue
๋ ์ผ๋ฐ ํ๋กํผํฐ๋ก ๋ณ๊ฒฝ๋์์ง๋ง
writable: false
, configurable: false
์์ฑ์ผ๋ก ์ธํด ์ญ์ ์ ๋ณ๊ฒฝ์ด ๋ถ๊ฐํฉ๋๋ค
์กฐ๊ธ ์ฌ์กฑ๐์ ๋ฌ์๋ฉด
return Object.defineProperty(...).hugeValue
ย ์ฒ๋ผ ํ๋กํผํฐ๋ฅผ ๋ช
์ํ์ง ์์ผ๋ฉด
Object.defineProperty์ ๋ฐํ๊ฐ์ ์๋ก ์ ์๋ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์
{ hugeValue: 1249999975000000, name: 'HugeValueInside' }
ย ์ ๊ฐ์ด ๊ฐ์ฒด๊ฐ ๋ฐํ๋ฉ๋๋ค
2. [Setter]
ํ๋กํผํฐ์ ๊ฐ์ ํ ๋นํ ๋ ํธ์ถ๋ฉ๋๋ค
์ผ๋ฐ์ ์ผ๋ก ๋ฐํ ๊ฐ์ด ์์ต๋๋ค
๋ง์ฝ ๋ฐํ ๊ฐ์ ์ค์ ํ๋ฉด, ๋น์ฐํ์ง๋ง ๊ฐ์ด ๋ฐํ๋ฉ๋๋ค
๊ทธ๋ฆฌ๊ณ ๊ทธ ๋์์ Assignment Operator ๊ฐ ๋๋ฐํ๋
Side-Effect ์ ์ ์ฌํฉ๋๋ค! (Operator: x = y)
Simple Assignment์์์ ๋ช
์ธ์ ์ํด,
๋จ์ํ(const
, let
, var
์๋) =
์ฐ์ฐ์ ์ฌ์ฉ์
์ฐ๋ณ์ ํ ๋น ์์ ๊ฐ(์์ ์คํํ๊ณ ํ๊ฐ๋ ๊ฐ)์ ๋ฐํํฉ๋๋ค
๋ฐฐ์์ด ๊น์์๋ก, ๊ฐ๊ฒฐํ๊ณ ๋ช
๋ฃํ ์ค๋ช
์ด ๊ฐ๋ฅ ํ๋ค๋๋ฐ
๋ฐฐ์์ด ๋ถ์กฑํด์ ๋ง์ด ๋๋ฌด ์ด๋ ต์ต๋๋ค ์ฃ์กํฉ๋๋ค๐ญ
์ดํด๋ฅผ ๋๊ธฐ ์ํด ์ฝ๋๋ก ์ค๋ช ํ ๊ฒ์
const obj = {
set someValue(a) {
return a
}
}
const unexpected = obj.someValue = 'Surprise!';
console.log(unexpected) // 'Surprise!';
๋ง์ ์ฝ๋๋ฅผ ๋ณด๋๊น ๋ณ ๊ฑฐ ์๋์ฃ ?
[Setter] ๋ ํ ๋น ์์ผ๋ก ํจ์๋ฅผ ํธ์ถํ๋๋ฐ, ๊ทธ ํจ์์ ๋ฐํ ๊ฐ์ด ์์ผ๋ฉด
์๋์น ์์ Side-Effect ๋ฅผ ๋ฐ์ํ ์ ์๋ค ๋ผ๋ ๊ฒ์ ์ค๋ช
ํ๊ณ ์ถ์์ต๋๋ค!
"๋ง์ฝ" ์ ๋ํ ์๊ธฐ๊ฐ ๋๋ฌด ๊ธธ์ด ์ก๋๋ฐ
๋ค์ [Setter]์ ๋ํด ์ค๋ช
ํ์๋ฉด ์๋์ ๊ฐ์ ๋ฌธ๋ฒ์ผ๋ก ์ฌ์ฉํฉ๋๋ค
const cat = {
_name: undefined,
set name(newName) {
this._name = newName;
},
call() {
console.log(this._name);
},
};
cat.name = 'DoonDoony';
cat.call(); // 'DoonDoony'
ํ๋กํผํฐ์ ๊ฐ์ ํ ๋นํ๋ ์์ ์ ๋ด๋ถ์ ์ผ๋ก๋ ์๋์ ๊ฐ์ ์์๋ก ์คํ๋ฉ๋๋ค
๐โโ๏ธ์ ๊ทผํ๋ ํ๋กํผํฐ๊ฐ ์๋ค๋ฉด
writable: false
๋ผ๋ฉด?TypeError
๊ฐ ๋ฐ์ํฉ๋๋ค๐
โโ๏ธ์ ๊ทผํ๋ ํ๋กํผํฐ๊ฐ ์๋ค๋ฉด
์ค๋ธ์ ํธ์ ์ฐ๊ฒฐ๋ ์์ [[Prototype]]
์ฒด์ธ์ ์ํํฉ๋๋ค.
์ด๋ฅผ ๋ ๊ฐ์ง ๊ฒฝ์ฐ๋ก ๋๋์ด ์๊ฐํด๋ณผ ์ ์์ต๋๋ค
๐
โโ๏ธ๋ชจ๋ [[Prototype]]
์ฒด์ธ์์ ํ๋กํผํฐ๊ฐ ๋ฐ๊ฒฌ๋์ง ์์ ๊ฒฝ์ฐ
1. Object extensible ํ๋ค๋ฉด, ์ง์ ํ๋กํผํฐ(Directly Present)๋ฅผ ์์ฑํ๊ณ ๊ฐ์ ํ ๋นํฉ๋๋ค
2. Object extensible(Object.preventExtensions(), Object.isExtensible()
) ํ์ง ์๋ค๋ฉด
โ ์ ํ๋กํผํฐ๋ฅผ ๋ง๋ค์ง ๋ชปํ๊ณ TypeError
๊ฐ ๋ฐ์ํฉ๋๋ค
๐์ฌ๊ธฐ์ Object extensible ํ๋ค๋ ๊ฒ์ Object.isExtensible(obj) === true
๋ฅผ ์๋ฏธ ํฉ๋๋ค
__proto__
์ ๊ฐ์ ์ถ๊ฐ, ๋ณ๊ฒฝํ๋ ๊ฒ ๋ํ ๊ฐ๋ฅํฉ๋๋ค๋ค์์ ๊ฐ๋จํ Object extensible ์ ๋ํ ์์ ์ฝ๋์ ๋๋ค
'use strict';
const parentCat = {
name: 'DoonDoon',
age: 10,
};
const childCat = Object.create(parentCat);
Object.assign(childCat, { name: 'DoonDoony', age: 3, favorite: 'Red Ball' });
// childCat ์ ํ์ฅ ๋ถ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค
Object.preventExtensions(childCat);
// childCat ์ด ํ์ฅ ๋ถ๊ฐ๋ฅํ์ง ํ์ธํฉ๋๋ค
console.log(Object.isExtensible(childCat)); // false
// ๊ธฐ์กด์ ํ๋กํผํฐ๋ฅผ ์์ ํฉ๋๋ค
childCat.favorite = 'Box';
console.log(childCat.favorite); // Box
// ๊ธฐ์กด์ ํ๋กํผํฐ๋ฅผ ์ญ์ ํฉ๋๋ค
delete childCat.favorite; // true
console.log(childCat.favorite); // undefined
// [[Prototype]] ์ ์ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํฉ๋๋ค
childCat.__proto__.gender = 'male';
console.log(Object.getPrototypeOf(childCat)); // { name: 'DoonDoon', age: 10, gender: 'male' }
childCat.gender = 'male'; // ๐
โโ๏ธ TypeError!
Object extensible ์ ๋ํ ์ฐธ๊ณ ๋งํฌ
๐โโ๏ธ์์ [[Prototype]]
์ฒด์ธ์์ ํ๋กํผํฐ๊ฐ ๋ฐ๊ฒฌ๋ ๊ฒฝ์ฐ
1. ํ๋กํผํฐ๊ฐ ์ฐ๊ธฐ ๊ฐ๋ฅ(writable: true
)ํ ๊ฒฝ์ฐ ์ง์ ํ๋กํผํฐ๋ฅผ ์์ฑํ๊ณ ๊ฐ์ ํ ๋นํฉ๋๋ค
2. ํ๋กํผํฐ๊ฐ ์ฐ๊ธฐ ๋ถ๊ฐ๋ฅ(writable: false
)ํ ๊ฒฝ์ฐ ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์์ต๋๋ค
์๊ฒฉ ๋ชจ๋์ ๊ฒฝ์ฐ TypeError
๊ฐ ๋ฐ์ํ๊ณ , ์๋ ๊ฒฝ์ฐ์ ์กฐ์ฉํ ์คํจํฉ๋๋ค
ํ๋กํผํฐ๊ฐ [Setter] ์ธ ๊ฒฝ์ฐ ํญ์ ์ด ์ธํฐ๊ฐ ํธ์ถ๋ฉ๋๋ค. ์ธํฐ๋ฅผ ๋ฎ์ด์ฐ๋ ์ผ์ ์ผ์ด๋์ง ์์ต๋๋ค
๋ง์ฝ ์ด ์ธํฐ๋ฅผ ๋ฎ์ด์ฐ๋ ค๋ฉด, Object.defineProperty ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค
์ถ๊ฐ์ ์ผ๋ก, ์์ [[Prototype]]
์ฒด์ธ์ ํ๋กํผํฐ๊ฐ ์์ ๋,
์ง์ ํ๋กํผํฐ๋ฅผ ๋ง๋ ๋ค๋ฉด ๊ฐ์ฒด์งํฅ์์ Overriding ์ด๋ผ ๋ถ๋ฅด๋ Shadowing ์ด ๋ฐ์ํฉ๋๋ค
โ ์ด ๋ด์ฉ์ ๋ค์์ ๊ธฐํ๊ฐ ๋๋ฉด Prototype ์ ๋ํ ๊ธ์ ์ฐ๋ฉด์ ํจ๊ป ๋ค๋ฃจ๋๋ก ํ๊ฒ ์ต๋๋ค ๐ถ
๊ฐ์ฒด์ ํ๋กํผํฐ ์กด์ฌ ํ๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค!
1. in
์ฐ์ฐ์ ์ฌ์ฉ
2. Object.hasOwnProperty
ํจ์ ์ฌ์ฉ
๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ฐจ์ด์ ์ in ์ฐ์ฐ์๋ [[Prototype]] ์ฒด์ธ์ ๋ชจ๋ ์ํํ๋ฉฐ ํค ์กด์ฌ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ๊ณ ,
hasOwnProperty ํจ์๋ ์ง์ ํ๋กํผํฐ์ ์กด์ฌ ์ฌ๋ถ๋ง์ ๊ฒ์ฌํ๋ค๋ ์ ์
๋๋ค!
const parent = { parentProp: 'Hey' };
const child = Object.create(parent);
child.childProp = 'Yay!';
// in ์ ์ฌ์ฉํ๋ฉด [[Prototype]] ์ฐ์์ ์กด์ฌํ๋ ํ๋กํผํฐ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค
console.log('parentProp' in child) // true
// hasOwnProperty ๋ฅผ ์ฌ์ฉํ๋ฉด ์ง์ ํ๋กํผํฐ์ ์กด์ฌ ์ฌ๋ถ๋ง ํ์ธํฉ๋๋ค
console.log(child.hasOwnProperty('parentProp')) // false
console.log(child.hasOwnProperty('childProp')) // true
Object.seal
, Object.freeze
ํจ์๋ ๋์ Object ๋ฅผ ์๋์ ๊ฐ์ ์ํ๋ก ๋ง๋ค ์ ์์ต๋๋ค
Object.defineProperty
๋ก Descriptor ๋ฅผ ๋ณ๊ฒฝํ๋ ํ์๋ฅผ ๋ง์function fail () {
'use strict';
const obj = { a: 1, b: 2 };
Object.seal(obj);
try {
obj.c = 3;
} catch (e) {
// ํ์ฅ ๋ถ๊ฐ๋ฅ ํ๊ธฐ ๋๋ฌธ์, TypeError!
console.error(e); // TypeError: Cannot add property c, object is not extensible
}
try {
Object.defineProperty(obj, 'b', { enumerable: false });
} catch (e) {
// ์ค์ ๋ถ๊ฐ๋ฅ ํ๊ธฐ ๋๋ฌธ์, TypeError!
console.error(e); // TypeError: Cannot redefine property: b
}
try {
delete obj.a;
} catch (e) {
// ์ญ์ ๋ถ๊ฐ๋ฅ ํ๊ธฐ ๋๋ฌธ์, TypeError!
console.error(e); // TypeError: Cannot delete property 'a' of #<Object>
}
}
fail();
Object.freeze ์ ๋์์ Object.seal ์ ๋ชจ๋ ๋์์ ํฌํจํ๊ณ
"ํ๋กํผํฐ ๊ฐ" ๋ํ ๋ณ๊ฒฝ ๋ถ๊ฐ ํ๊ฒ ๋ง๋ญ๋๋ค
ํ์ง๋ง, ์ค์ฒฉ๋ ์ ๊ทผ์ ๊ฐ ๋ณ๊ฒฝ์ ๊ฐ๋ฅํฉ๋๋ค
(obj.a = { b: 1 }
์ด๋ผ๋ฉด obj.a ๋ ๋ณ๊ฒฝ ๋ถ๊ฐ ํ์ง๋ง, obj.a.b ๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํฉ๋๋ค)
function freeze () {
'use strict';
const catWillBefrozen = {
name: 'DoonDoony',
age: 3,
furColors: ['white', 'coffee'],
friends: [
{ name: 'TT', age: 3 },
{ name: 'Coco', age: 3 },
],
};
Object.freeze(catWillBefrozen);
try {
catWillBefrozen.name = 'TT'; // ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค
} catch (e) {
console.error(e); // TypeError: Cannot assign to read only property 'name' of object '#<Object>'
}
catWillBefrozen.furColors.push('pink'); // ํ์ง๋ง ๋ฐฐ์ด ์กฐ์์ ๊ฐ๋ฅํฉ๋๋ค
console.log(catWillBefrozen.furColors); // ['white', 'coffee', 'pink']
catWillBefrozen.friends[0].name = 'Momo'; // ๊ฐ์ฒด ์กฐ์ ๋ํ ๊ฐ๋ฅํฉ๋๋ค
console.log(catWillBefrozen.friends[0]) // { name: 'Momo', age: 3 }
}
freeze();
๊ฐ์ฒด์ ๋ณต์ฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ธ์ด๋ฅผ ๋ ๋ ํ๋ก๊ทธ๋๋ฐ์์ ๋ณดํต ๋ ๊ฐ์ง ํํ๋ก ์ด๋ฃจ์ด์ง๋๋ค
๋ฐ๋ก ์์ ๋ณต์ฌ(Shallow Copy), ๊น์ ๋ณต์ฌ(Deep Copy) ์
๋๋ค
์์ ๋ณต์ฌ๋ Object.assign
๋๋ Object Spread Operator({ ... }) ๋ก ์์ ๋ณต์ฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค
๊น์ ๋ณต์ฌ๋ JSON.stringify
, JSON.parse
๋ฅผ ์ด์ฉํ์ฌ ๊ฐ๋ฅํฉ๋๋ค
๋์ ์ฐจ์ด์ ์, ์์ ๋ณต์ฌ์ ๊ฒฝ์ฐ ํ๋กํผํฐ๊ฐ object(๋ฐฐ์ด, ํจ์ ํฌํจ) ๋ผ๋ฉด
๊ฐ์ด ์๋ ์ฐธ์กฐ๋ก ๋ณต์ฌ ๋๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด, ๊ฐ์ฒด, ํจ์์ ๋ํ ๋ณ๊ฒฝ์ด ์๊ธฐ๋ฉด
๋ชจ๋ ๋ณต์ฌ๋ ๊ฐ์ฒด๊ฐ ๊ณต์ ํ๋ค๋ ์ ์
๋๋ค
๊น์ ๋ณต์ฌ ๋ฐฉ๋ฒ์, JSON ์ง๋ ฌํ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ง์ ๋ณต์ฌํ ์ ์๊ธฐ ๋๋ฌธ์
ํจ์์ ๊ฐ์ ํ๋กํผํฐ๋ ๋ณต์ฌ๊ฐ ๋์ง ์๋๋ค๋ ์ ์
๋๋ค!
const cat = {
name: 'DoonDoony',
age: 3,
furColors: ['white', 'coffee'],
speak () {
console.log(this.name);
},
};
// Object.assign ์ ํด ๋ณต์ฌ๋ฅผ ์๋
const deepCopiedCat = JSON.parse(JSON.stringify(cat));
const newCat = Object.assign({}, cat);
const newCat2 = { ...cat };
function testCopy (origin, new_) {
'use strict';
// newCat ์ ๊ฐ ์กฐ์
new_.furColors.push('pink');
new_.name = 'TT';
new_.speak.prop = 'function Prop';
// ์ ๋ณต์ฌ๋์ด ์๋ก ๋ค๋ฅธ ๊ฐ์ ์ถ๋ ฅํ๋ค
console.log(new_.name);
console.log(origin.name);
// ์! ํ๋กํผํฐ์ ๊ฐ์ด ๋ฐฐ์ด์ธ ๊ฒฝ์ฐ ์ฐธ์กฐ ๊ฐ์ ๋๊ธฐ๊ธฐ ๋๋ฌธ์, ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค
console.log(new_.furColors);
console.log(origin.furColors);
new_.speak(); // 'TT'
origin.speak(); // 'DoonDoony'
console.log(new_.speak.prop);
console.log(origin.speak.prop);
}
testCopy(cat, newCat); // 'TT', 'DoonDoony', ['white', 'coffee', 'pink'], 'function Prop'
testCopy(cat, newCat2); // 'TT', 'DoonDoony', ['white', 'coffee', 'pink', 'pink'], 'function Prop'
try {
testCopy(cat, deepCopiedCat); // ํจ์๊ฐ ๋ณต์ฌ๋์ง ์์, speak ํ๋กํผํฐ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค
} catch (e) {
console.error(e);
}
testCopy ํจ์์ newCat2 ๋ฅผ ๋ฃ์ ๊ฒฝ์ฐ์๋
์ด์ ์ 'pink' ๋ฌธ์์ด์ด ์ถ๊ฐ๋ ๋ฐฐ์ด์ด ๊ทธ๋๋ก ๊ณต์ ๋์ด, 'pink' ๋ฌธ์์ด์ด ๋ ๊ฐ ์กด์ฌํฉ๋๋ค
JSON ์ง๋ ฌํ ๋ฐฉ๋ฒ์ผ๋ก ๊น์ ๋ณต์ฌ๋ฅผ ๊ตฌํํ ๊ฒฝ์ฐ์๋
try - catch ๊ตฌ๋ฌธ์์ ์ฒ๋ผ, speak ๋ผ๋ ํจ์ ํ๋กํผํฐ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค
(ํจ์๋ JSON ์ง๋ ฌํ๊ฐ ๋ถ๊ฐ๋ฅ ํ๊ธฐ ๋๋ฌธ์ด์ฃ ๐)
ES6 ์์ Object ๋ฅผ ์กฐ์ํ๋ ๋ช ๊ฐ์ง ๋ฌธ๋ฒ์ด ์ถ๊ฐ๋์์ต๋๋ค
Object Spread Operator
์ฃผ๋ก Object ์ ์์ ๋ณต์ฌ (๋ฐ๋ก ์์ ๋ด์ฉ์ด ์์ด์!) ์ ์ฌ์ฉ๋ฉ๋๋ค
const doondoony = {
name: 'DoonDoony',
age: 3,
favorite: 'Red Ball',
color: ['white', 'coffee'],
};
// doondoony ๊ฐ์ฒด์ ๋ชจ๋ ๊ฐ์ ๋ณต์ฌํ๊ณ , ์ค๋ณต๋๋ ํ๋กํผํฐ๋ ์
๋ฐ์ดํธ ํฉ๋๋ค
const doondoonyJr = { ...doondoony, name: 'DoonDoon', age: 1 };
console.log(doondoony.age); // 3
console.log(doondoonyJr.age); // 1
Rest Parameter
Object ๋ํ ๋๋จธ์ง๋ฅผ ๋ฐํํ๋ Rest Parameter ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค
๋ง์ฝ ํด์ฒด ํ๋ ค๋ Object ์ ์๋ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ๋ฉด undefined ๊ฐ ๋ฐํ๋ฉ๋๋ค
const doondoony = {
name: 'DoonDoony',
age: 3,
favorite: 'Red Ball',
color: ['white', 'coffee'],
};
// ๋๋จธ์ง
const { name, ...rest } = doondoony;
const { catName, ...rest } = doondoony;
console.log(name) // 'DoonDoony'
console.log(catName) // undefined, ์๋ ํ๋กํผํฐ๋ช
์
๋๋ค!
console.log(rest) // {age: 3, favorite: 'Red Ball', color: ['white', 'coffee']}
Object Destructuring
Object์์ ๋ช๋ช์ ํ๋กํผํฐ์ ์ ๊ทผํ ๋ ์๋์ ๊ฐ์ ๋ฌธ๋ฒ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค
const doondoony = {
name: 'DoonDoony',
age: 3,
favorite: 'Red Ball',
color: ['white', 'coffee'],
};
const { name, age } = doondoony;
console.log(`${name} is ${age} years old`); // DoonDoony is 3 years old
์ด๊ฒ์ ์์ฉํ์ฌ, ํจ์์ ์ธ์๊ฐ Object ์ธ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ด ์ฒ๋ฆฌํ ์ ์์ต๋๋ค
const doondoony = {
name: 'DoonDoony',
age: 3,
favorite: 'Red Ball',
color: ['white', 'coffee'],
};
function howOldAreYou ({ name, age }) {
console.log(`${name} is ${age} years old`);
}
howOldAreYou(doondoony); // DoonDoony is 3 years old
Property Value Shorhand (ํ๋กํผํฐ ํ ๋น ๋จ์ถ๊ตฌ๋ฌธ)
Object์ ํ๋กํผํฐ๊ฐ ๋ณ์๋ช ๊ณผ ๋์ผํ ๊ฒฝ์ฐ, ๋ณ์๋ช ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค
function makeCuteCat (name, age, color) {
return {
name, // name: name ์ด๋ผ๊ณ ์๋๋ ์์ฑํด์ผ ํ์์ง๋ง, ๋จ์ถ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ฉด ๊ฐ์ ๋์์ ํฉ๋๋ค
age,
color,
};
}
const doondoony = makeCuteCat('DoonDoony', 3, ['white', 'coffee']);
console.log(doondoony); // {name: 'DoonDoony', age: 3, color: ['white', 'coffee']}
Method definition shorthand(๋ฉ์๋ ์ ์ ์ถ์ฝ ๋ฌธ๋ฒ)
Object ๋ด๋ถ์ ํจ์๋ฅผ ๊ฐ์ผ๋ก ๊ฐ์ง ํ๋กํผํฐ (= ๋ฉ์๋) ๋ฅผ ๋ง๋ค ๊ฒฝ์ฐ
์๋์ ๊ฐ์ ์ถ์ฝ ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค
const doondoony = {
name: 'DoonDoony',
age: 3,
// speak: function() {} ๊ณผ ๊ฐ์ ๋ฐฉ์์์ ์ถ์ฝ ํด์ ์์ฑํ ์ ์์ต๋๋ค
speak () {
console.log(this.name);
},
};
Object ๋ฉ์๋ ์ถ์ฝ๋ฌธ๋ฒ๊ณผ class ๋ฉ์๋๋ฅผ ์ ์๋ ์กฐ๊ธ์ ์ฐจ์ด๊ฐ ์์ต๋๋ค
๋ฐ๋ก ์ฝค๋ง(,) ๋ก ๊ตฌ๋ถํด์ผ ํ๋ค๋ ์ ์
๋๋ค (ํ๋กํผํฐ์ด๊ธฐ ๋๋ฌธ์ ๋น์ฐํ์ง๋ง ๐
)
const doondoony = {
name: 'DoonDoony',
speak () {
console.log(this.name);
},
// ๋ค์ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ ค๋ฉด ์ฝค๋ง(,) ๋ฅผ ์ฌ์ฉํด ๊ตฌ๋ถํด์ผ ํฉ๋๋ค
age: 3,
};
const DoonDoony = class {
constructor (name, age) {
this.name = name;
this.age = age;
}
// constructor ์ speak ์ฌ์ด์ ์ฝค๋ง(,) ์์
speak () {
console.log(this.name)
}
};
doondoony.speak(); // 'DoonDoony'
new DoonDoony('DoonDoony', 3).speak(); // 'DoonDoony'
๋์์๊ณ ์์ฒญ๋๊ฒ ๊ธด ๊ธ ์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค ๐
ํญ์ ์๋ชป๋ ์ ๋ณด๋ ๋๊ธ ๋จ๊ฒจ ์ฃผ์๋ฉด ์์ ํ ๋ก ํ๊ฒ ์ต๋๋ค.
๊ธด ๊ธ์ ๋ง์น๋ฉฐ ์ด ๊ธ์ ์ฐ๊ฒ๋ ๊ณ๊ธฐ์ ๋ํด ๋ค์ ์ง์ด๋ณด์์ต๋๋ค
์ ๋ฆฌ๋ฅผ ํ๊ณ ๋๋๊น( ๊ทธ๋ ๋ค๊ณ Object ๋ผ๋ ๊ฒ์ ์์ ํ ์ดํดํ ๊ฒ์ ์๋์ง๋ง )
๊ทธ ์ ์ ๋ชจ๋ฅด๋ ์์ ์๋, ๊ฐ์ ์ฐธ์กฐ ๋ฐฉ๋ฒ
๊ทธ๋ฆฌ๊ณ ๋ค์ํ Object ์ ๋ฉ์๋ ๋ฑ์ ๋ํด ์์ธํ ์ ์ ์์์ต๋๋ค
์ฌ์ค Object ๋๋ถ๋ถ์ ๋ฉ์๋์ ๋ํด ๋ค๋ฃจ์์ง๋ง
Object.create ์ ๋ํด์๋ ์ต ์๋จ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ ์ด ๋๊ธฐ๋ง ํ๊ณ ์๋ฌด๋ฐ ์ค๋ช
์ด ์์๋๋ฐ์
์ดํ์๋ Object.create ์ ๊ทธ๊ฒ์ ๋๋ฌ์ผ [[Prototype]] ์ ๋ํด ์ค๋ช
ํ๊ณ
๊ถ๊ทน์ ์ผ๋ก ์ ๊ฐ ๊ณต๋ถํ๊ณ ์ถ์๋ ์ฃผ์ ์ธ ๊ฐ์ฒด๋ฅผ ํด๋์ค์ฒ๋ผ ์ฌ์ฉํ๊ธฐ ์ ๋ํด ๋จ๊ธฐ๊ณ ์ถ์ต๋๋ค!
๊ฐ์ฌํฉ๋๋ค!
์๋ดค์ต๋๋ค!