[JS] JavaScript ์๋ฐ์คํฌ๋ฆฝํธ Map ๋ ์ ์ฌ์ฉํ๊ธฐ
Map์ key, value๋ก ์ด๋ฃจ์ด์ง ์์๊ฐ ์๋ ์ปฌ๋ ์ ์ด๋ค. ์ฝ์ ์์๋ฅผ ๊ธฐ์ตํ๋ฉฐ key/value ์ถ๊ฐ/์ ๊ฑฐ๊ฐ ๋น๋ฒํ ๋ ๊ฐ์ฒด๋ณด๋ค ๋ ์ข์ ์ฑ๋ฅ์ ๊ฐ์ง๋ค MDN - Map ํ์ด์ง๋ฅผ ๋ณด๋ฉด ์๋์ ๊ฐ์ด ์ ํ์๋ค.
Map: ํค-๊ฐ ์์ ๋น๋ฒํ ์ถ๊ฐ ๋ฐ ์ ๊ฑฐ์ ๊ด๋ จ๋ ์ํฉ์์๋ ์ฑ๋ฅ์ด ์ข ๋ ์ข์ต๋๋ค.
Object: ํค-๊ฐ ์์ ๋น๋ฒํ ์ถ๊ฐ ๋ฐ ์ ๊ฑฐ์ ์ต์ ํ๋์ง ์์์ต๋๋ค.
์ค์ ๋ก ๋๋ค ์ซ์ 10,000๊ฐ๋ก ๊ตฌ์ฑ๋ ๊ฐ์ฒด๋ฅผ ์ถ๊ฐ/์ญ์ ํ ๋ Map์ 901 ops/s, ๊ฐ์ฒด๋ 183 ops/s๋ก ์ธก์ ๋๋ค. ์ฆ, 1์ด ๋์ Map์ 901๋ฒ์ ์์ ์ ์ฒ๋ฆฌํ๊ณ , ๊ฐ์ฒด๋ 183๋ฒ์ ์์ ์ ์ฒ๋ฆฌํ๋ค. Map์ด ์ผ๋ฐ ๊ฐ์ฒด๋ณด๋ค ๊ฑฐ์ 4~5๋ฐฐ ๊ฐ๋ ๋น ๋ฅด๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค. ๋ฌผ๋ก ์ด ๋ฒค์น๋งํฌ๋ฅผ 100% ์ ๋ขฐํ ์ ์์ง๋ง key/value ์ถ๊ฐ/์ ๊ฑฐ์ ์์ด Map์ด ๊ฐ์ฒด๋ณด๋ค ์ต์ ํ๋ ๊ฒ์ ์๋ช ํด๋ณด์ธ๋ค.
๐กops/s๋ ์ด๋น ์ฐ์ฐ ํ์๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
๋ด์ฅ ํค
ํค๊ฐ ์๋ ๋น ๊ฐ์ฒด๋ผ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ชจ๋ ๊ฐ์ฒด๋ Object.prototype
์ ์ ์๋ ์์ฑ๊ณผ ๋ฉ์๋๋ฅผ ์์๋ฐ๋๋ค. ์ฆ, ๋น ๊ฐ์ฒด๋ผ๋ ํ๋กํ ํ์
์ฒด์ธ์ ์ํด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค. ์ด๋ ์ ์ฌ์ ์ธ ๋ฒ๊ทธ๋ก ์ด์ด์ง ์ ์๋ค.
const myMap = {};
myMap.valueOf; // [Function: valueOf]
myMap.toString; // [Function: toString]
myMap.hasOwnProperty; // [Function: hasOwnProperty]
myMap.isPrototypeOf; // [Function: isPrototypeOf]
myMap.propertyIsEnumerable; // [Function: propertyIsEnumerable]
myMap.toLocaleString; // [Function: toLocaleString]
myMap.constructor; // [Function: Object]
์ฐธ๊ณ ๋ก ES2022์ ๊ณต๊ฐํ Object.hasOwn(obj, propKey)
๋ฉ์๋๋ฅผ ์ด์ฉํ๋ฉด ์ธ์๋ก ๋๊ธด ํ๋กํผํฐ๊ฐ ๊ฐ์ฒด ์์ ์ด ์์ ํ ๊ฒ์ธ์ง ํ์ธํ ์ ์๋ค. e.g. Object.hasOwn(myMap, valueOf)
→ false
Map์ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ๋ฌธ์ ์์ ์์ ๋ก์ธ ์ ์๋ค.
๋ฐ๋ณต
๋ง์ฝ ์์ฑ์ ํจ์์ ํ๋กํ ํ์
์ ์์ ํ ์ํฉ์์ for in
์ผ๋ก ์ํํ๋ฉด ์์ ์ด ์์ ํ์ง ์์ ํ๋กํผํฐ๋ ์ถ๋ ฅํ๋ค. ์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด if (Object.hasOwn(...))
๊ฐ์ ์กฐ๊ฑด์ ์ถ๊ฐ ํ ์ ์์ง๋ง ๋ฒ๊ฑฐ๋กญ๋ค.
// JS ๋ด์ฅ ํ๋กํ ํ์
์ ์์ ํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์๋๋ค.
// ์๋๋ ์์๋ฅผ ์ํ ์์ ์ธ ์ ์ฐธ๊ณ
Object.prototype.fullName = 'Obama';
const obj = { name: 'smith', age: 30 };
for (const key in obj) {
console.log(key); // name, age, fullName
}
Map์ ์ดํฐ๋ฌ๋ธ์ด๋ฏ๋ก for of
๋ฌธ์ผ๋ก ์ํํ ์ ์์ผ๋ฉฐ, ์์ ๊ฐ์ ๋ฌธ์ ๋ ๋ฐ์ํ์ง ์๋๋ค. ๋ํ, ๊ตฌ์กฐ ๋ถํด ํ ๋น์ ์ด์ฉํด key, value๋ฅผ ํ ๋ฒ์ ๊ฐ์ ธ์ฌ ์ ์์ด ํธํ๋ค.
const myMap = new Map([
['name', 'smith'],
['age', 30],
]);
for (const [key, value] of myMap) {
console.log(`${key}: ${value}`); // name: smith, age: 30
}
Symbol.iterator
๋ฉ์๋๊ฐ ๊ตฌํ๋์ด ์๋ ๊ฐ์ฒด๋ฅผ ์ดํฐ๋ฌ๋ธ(iterable)์ด๋ผ๊ณ ํ๋ค. ๊ฐ๋จํ ๋งํ๋ฉด ์ดํฐ๋ฌ๋ธ์ ๋ฐ๋ณต ๊ฐ๋ฅํ ๊ฐ์ฒด๋ค. ๋ฐฐ์ด, ๋ฌธ์์ด์Symbol.iterator
๋ฉ์๋๊ฐ ์ด๋ฏธ ๊ตฌํ๋์ด ์๋ ๋ํ์ ์ธ ๋ด์ฅ ์ดํฐ๋ฌ๋ธ์ด๋ค. ์ดํฐ๋ฌ๋ธ์ ์ฌ์ฉํ๋ฉด ์ด๋ค ๊ฐ์ฒด๋ โfor of
๋ฐ๋ณต๋ฌธ โ์ ๊ฐ ๋ฌธ๋ฒ โ๋ฐฐ์ด ๊ตฌ์กฐ๋ถํด ํ ๋น์ ๋์์ผ๋ก ์ฌ์ฉํ ์๋ ์๋ค.
ํค ์์
Map์ ์ฝ์ ์์๋ฅผ ์ ์งํ๋ฏ๋ก, ์์๋ฅผ ์ํํ ๋๋ ํญ์ ์ผ์ ํ ์์๋ก ๋ฐํํ๋ค. ์ด๋ฐ ํน์ฑ ๋๋ฌธ์ Map์ ๊ตฌ์กฐ ๋ถํด ํ ๋นํ์ฌ ์์์ ๋ ์ฝ๊ฒ ์ก์ธ์คํ ์ ์๋ค.
const user = { name: 'smith', age: 30 };
const map = new Map(Object.entries(user));
const [firstEntry, secondEntry] = map; // ['name', 'smith'], ['age', 30]
const [[firstKey, firstValue]] = map; // firstKey -> 'name', firstValue -> 30
๋ณต์ฌ
๊ฐ์ฒด๋ ์ ๊ฐ๋ฌธ๋ฒ์ด๋ Object.assign
๋ฉ์๋๋ก ์ฝ๊ฒ ๋ณต์ฌํ ์ ์๋ค.
const user = { name: 'smith', age: 30 };
const cloned1 = { ...user };
const cloned2 = Object.assign({}, user);
Map ์์ฑ์๋ [key, value]
ํํ์ ์ดํฐ๋ฌ๋ธ์ ์ฌ์ฉํ๋ฏ๋ก ๊ธฐ์กด ๋งต ๊ฐ์ฒด๋ฅผ ์์ฑ์์ ์ ๋ฌํ๋ฉด ๋ณต์ฌํ ์ ์๋ค.
const userMap = new Map([
['name', 'smith'],
['age', 30],
]);
const cloned = new Map(userMap); // Map(2) {'name' => 'smith', 'age' => 30}
๊น์ ๋ณต์ฌ๋ structuredClone ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
const users = { smith: { age: 30 }, john: { age: 20 } };
// entries -> [['smith', { age: 30 }], ['john', { age: 20 }]]
// ์์ ๋ณต์ฌ
const usersMap = new Map(Object.entries(users));
const clonedMap = new Map(usersMap);
usersMap.get('smith') === clonedMap.get('smith'); // true
// ๊น์ ๋ณต์ฌ
const clonedMap = new Map(structuredClone(usersMap));
usersMap.get('smith') === clonedMap.get('smith'); // false
ํฌํผ ํจ์ โก๏ธ
Object.fromEntries
, Object.entries
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ฒด โ Map ๋ณํ์ ์์ ๋กญ๊ฒ ํ ์ ์๋ค.
const user = { name: 'smith', age: 30 };
const map = new Map(Object.entries(user)); // Map(2) {'name' => 'smith', 'age' => 30}
const userFromMap = Object.fromEntries(map); // {name: 'smith', age: 30}
์๋ก์ด Map ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ [[key ,value], [key, value]]
ํํ์ ์ธ์๋ก ๋๊ฒจ์ผ ํ๋ค. ๊ทธ๋ฆฌ ์ง๊ด์ ์ด์ง ์๋ค. Object.entries
๋ฅผ ํ์ฉํด ํฌํผ ํจ์๋ฅผ ๋ง๋ค์ด๋๋ฉด ๋ ํธํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
const makeMap = (obj) => new Map(Object.entries(obj));
const myMap = makeMap({ name: 'smith', age: 30 }); // Map(2) {'name' => 'smith', 'age' => 30}
์๋๋ ํ์
์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ ๋ ์์. V
์ ๋ค๋ฆญ ํ์
์ ์ ๋ฌํ์ง ์์ผ๋ฉด unknown
์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๊ฐ์ง๋ฉฐ, key๋ string
, value๋ V
์ ๋ค๋ฆญ ํ์
์ ๊ฐ์ง๋ Map ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
const makeMap = <V = unknown,>(obj: Record<string, V>) => {
return new Map<string, V>(Object.entries(obj));
};
Map ํ์ฉ โก๏ธ
์๋ฐ์คํฌ๋ฆฝํธ์์ string๊ณผ symbol ํ์ ๋ง ๊ฐ์ฒด์ key๋ก ์ฌ์ฉํ ์ ์๋ค. ๋ฐ๋ฉด Map์ ์์ํ์ ๋ฌผ๋ก ๊ฐ์ฒด ๊ฐ์ ์ฐธ์กฐํ๋ key๋ก ์ฌ์ฉํ ์ ์๋ค.
myMap.set({}, value);
myMap.set([], value);
myMap.set(document.body, value);
myMap.set(function () {}, value);
๐ก ๋ฉํ๋ฐ์ดํฐ๋ ํน์ ๋ฐ์ดํฐ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ ๋ฐ์ดํฐ๋ฅผ ์๋ฏธํ๋ค.
์ด๋ฅผ ํ์ฉํ๋ฉด ๊ฐ์ฒด๋ฅผ ์ง์ ์์ ํ์ง ์๊ณ ๊ฐ์ฒด์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ฒฐํ๋ ๋ฐฉ์์ผ๋ก ์ํ๋ฅผ ๋ค๋ฃฐ ์ ์๋ค. ์๋ ์์์์ $h3
์์์ ๋ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ Map ๊ฐ์ฒด์ ์ ์ฅํด๋๊ณ , get
๋ฉ์๋๋ก ๋ฉํ๋ฐ์ดํฐ์ ์ ๊ทผํ๊ณ ์๋ค.
const $h3 = document.querySelector('h3');
const metadata = new Map();
metadata.set($h3, { color: 'red' });
metadata.get($h3); // {color: 'red'}
์๋ณธ ๊ฐ์ฒด(toDoList)์ ์ํฅ์ ์ฃผ์ง ์์ผ๋ฉด์ ์์ ๋ฐ์ดํฐ(focused
์ํ)๋ฅผ ์ค์ ํ ๋๋ ์ ์ฉํ๋ค.
const metadata = new Map();
metadata.set(toDoList, { focused: true });
metadata.get(toDoList); // {focused: true}
WeakMap
๐ก WeakMap๊ณผ ์ ์ฌํ WeakSet๋ ์๋ค. WeakSet ์ญ์ key์ ๊ฐ์ฒด(์ฐธ์กฐํ)๋ง ์ ์ฅํ ์ ์๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ ๋์ ์ผ๋ก ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ค. ๊ฐ์ฒด๋ ํจ์๋ฅผ ์์ฑํ๋ฉด ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋๊ณ , ํด๋น ๊ฐ์ฒด๊ฐ ๋ ์ด์ ์ฐธ์กฐ๋์ง ์์ผ๋ฉด(์ฌ์ฉํ๋ ๊ณณ ์์; ๋๋ฌ ๋ถ๊ฐ) ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ํ์ฌ ์์์ ํ๋ณดํ๋ค.
let user = { name: 'smith', age: 30 };
user = null;
// ์ฐธ์กฐ๋ฅผ null๋ก ๋ฎ์ด์จ์ ๊ฐ์ฒด์ ๋์ด์ ์ ๊ทผํ ์ ์์
// ๋ฐ๋ผ์ ์ ๊ฐ์ฒด๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ๋ฉ๋ชจ๋ฆฌ์์ ์ญ์ ๋จ
โ ๊ฐ์ฒด ํ๋กํผํฐ, โก๋ฐฐ์ด ์์, โขMap/Set์ ๊ตฌ์ฑํ๋ ์์๋ ์์ ์ด ์ํ ์๋ฃ๊ตฌ์กฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์ ์์ผ๋ฉด ๋๋ฌํ ์ ์๋ ๊ฐ์ผ๋ก ์ทจ๊ธํด์ ๋ฉ๋ชจ๋ฆฌ์์ ์ญ์ ๋์ง ์๋๋ค.
์๋ ์ฝ๋์์ smith
๋ณ์๋ฅผ null
๋ก ๋ฎ์ด์ผ๋๋ฐ๋ ๋ถ๊ตฌํ๊ณ users
์์ ์ฌ์ ํ ์ ๊ทผํ ์ ์๋ค. smith
๊ฐ ๊ฐ๋ฆฌ์ผฐ๋ ๊ฐ์ฒด๋ users
๋ฐฐ์ด ์์๋ก ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ ๋์์ด ๋์ง ์์ ๊ฒ์ด๋ค.
let smith = { name: 'smith' };
const users = [smith];
smith = null;
console.log(users); // [{"name": "smith"}]
Map์์ ๊ฐ์ฒด๋ฅผ key/value๋ก ์ฌ์ฉํ์ ๋๋ Map์ด ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์๋ ํ key ํน์ value๋ก ์ฌ์ฉํ ๊ฐ์ฒด๋ ๋ฉ๋ชจ๋ฆฌ์ ๊ณ์ ๋จ๊ฒ ๋๋ค.
let smith = { name: 'smith' };
const map = new Map();
map.set(smith, '์ค๋ฏธ์ค'); // Map(1) {{name: 'smith'} => '์ค๋ฏธ์ค'}
smith = null;
for (const key of map.keys()) console.log(key); // {name: 'smith'}
๋ฐ๋ฉด WeakMap์์ ๊ฐ์ฒด๋ฅผ key๋ก ์ฌ์ฉํ ๊ฒฝ์ฐ, ํด๋น ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ณณ์ด ์๋ค๋ฉด ๊ฐ๋น์ง ์ปฌ๋ ์ ๋์์ด ๋ผ์ ๋ฉ๋ชจ๋ฆฌ์ WeakMap์์ ์ญ์ ๋๋ค.
const weakMap = new WeakMap();
let smith = { name: 'smith' };
weakMap.set(smith, '์ค๋ฏธ์ค'); // WeakMap {{name: 'smith'} => '์ค๋ฏธ์ค'}
smith = null;
console.log(weakMap); // WeakMap {}
WeakMap์ key๋ ๊ฐ์ฒด๋ง ์ฌ์ฉํ ์ ์๋ ํน์ง์ด ์๋ค.
const weakMap = new WeakMap();
const smith = { name: 'smith' };
weakMap.set('smith', smith); // Invalid value used as weak map key
weakMap.set(smith, 'smith'); // OK
๐ก Map๊ณผ ๋ฌ๋ฆฌ WeakMap์ ์ดํฐ๋ฌ๋ธ์ด ์๋๋ค. ๋ฐ๋ผ์ for of
๋ฐ๋ณต๋ ์ฌ์ฉํ ์ ์๋ค.
WeakMap์์ keys()
, values()
, entries()
๊ฐ์ ์ํ(traversal) ๋ฉ์๋๋ฅผ ์ง์ํ์ง ์๋๋ค. ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์๋ํ๋ ์์ ์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ๊ฒฐ์ ํ๋ฉฐ, ์ ํํ ๋์ ์์ ์ ์์ธกํ ์ ์๋ค. ์ฆ, ๊ฐ์ฒด๋ก ์กด์ฌํ๋ WeakMap ํค(key)๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ์ธ์ ์ญ์ ๋ ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ WeakMap ์์ ๊ฐ์๋ฅผ ํ์
ํ๋ ๊ฒ๋ ๋ถ๊ฐ๋ฅํ๋ค. ์ด๋ฌํ ์ด์ ๋ก ์์ ์ ์ฒด๋ฅผ ๋์์ผ๋ก ํ๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ง ์๋ ๊ฒ.
WeakMap์์ ์๋ ๋ฉ์๋๋ง ์ฌ์ฉํ ์ ์๋ค.
weakMap.get(key)
weakMap.set(key, value)
weakMap.delete(key)
weakMap.has(key)
์ง๋ ฌํ / ์ญ์ง๋ ฌํ
JSON.stringify(value[, replacer[, space]])
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ฅผ JSON์ผ๋ก ๋ณํ(์ง๋ ฌํ)ํ ๋ JSON.stringify
๋ฅผ ์ฌ์ฉํ๋ค. JSON.stringify
๋๋ฒ์งธ ์ ํ์ ํ๋ผ๋ฏธํฐ๋ก replacer๋ฅผ ๋ฐ์ ์ ์๋๋ฐ, ์ง๋ ฌํ์ ๊ฐ์ ๋ณํํ๊ฑฐ๋ ์ํ๋ ์์ฑ๋ง ํฌํจ์ํค๊ธฐ ์ํด ์ฌ์ฉํ๋ค. replacer๋ ์ฉ๋์ ๋ฐ๋ผ ํจ์์ ๋ฐฐ์ด 2๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
- ํจ์ : ๋ณํ ์ ๊ฐ ๋ณํ. ํจ์ ์ธ์๋ก key, value๋ฅผ ๋ฐ์
- ๋ฐฐ์ด : ์ง์ ํ ํ๋กํผํฐ๋ง ๊ฒฐ๊ณผ์ ํฌํจ
replacer ํบ์๋ณด๊ธฐ
replacer ํจ์ ๋ฐํ๊ฐ์ด null
, undefined
์ด๋ฉด ๊ฒฐ๊ณผ์์ ์ ์ธ๋๋ค. ๋ฐ๋ผ์ ์๋ replacer ํจ์๋ string ํ์
์ value๋ ๊ฒฐ๊ณผ์ ํฌํจํ์ง ์๋๋ค.
// ํจ์ replacer ์์ 1
function replacer(key, value) {
if (typeof value === 'string') return undefined;
return value;
}
const foo = {
foundation: 'Mozilla',
model: 'box',
week: 45,
transport: 'car',
month: 7,
};
const jsonString = JSON.stringify(foo, replacer); // '{"week":45,"month":7}'
replacer ํจ์๋ ์ฒซ๋ฒ์งธ ์ํ์ JSON.stringify
์ ๋๊ฒผ๋ ๊ฐ์ฒด๋ฅผ value๋ก ๋ฐ๋๋ค. ์ด๋ ๊ฐ์ฒด ๊ตฌ์กฐ์ value๋ฅผ ๋ฆฌํดํ์ง ์์ผ๋ฉด ๋์ด์ ์ํํ์ง ์๋๋ค. ์ฆ, ๊ฐ์ฒด key/value ์์ ๋ํ ์ํ๋ ๋๋ฒ์งธ๋ถํฐ ์ด๋ค์ง๋ ์
์ด๋ค. ๊ฐ์ฒด key์ value๊ฐ ๊ฐ์ฒด ์ผ ๋๋ ์ฌ๊ท์ ์ผ๋ก ๋์ํ์ฌ ์ํ ๋ฐฉ์์ ๋์ผํ๋ค.
// ํจ์ replacer ์์ 2
function replacer(key, value) {
console.log('key:', key, '|', 'value:', value);
if (typeof value === 'string') return value + '-modified';
return value;
}
JSON.stringify({ name: 'smith' }, replacer);
// [์ํ 1] key: '', value: {name: 'smith'} -> JSON.stringify ์ธ์๋ก ๋๊ฒผ๋ ๊ฐ์ฒด
// [์ํ 2] key: 'name', value: 'smith' -> ์ฒซ๋ฒ์งธ key/value ์ํ
// [๊ฒฐ๊ณผ] '{"name":"smith-modified"}'
replacer๊ฐ ๋ฐฐ์ด์ผ ๋ ํฌํจํ๊ณ ์ถ์ key๋ฅผ ๋ฐฐ์ด ์์๋ก ์ถ๊ฐํ๋ค.
// ๋ฐฐ์ด replacer ์์
const foo = {
foundation: 'Mozilla',
model: 'box',
week: 45,
transport: 'car',
month: 7,
};
JSON.stringify(foo, ['weak, month']); // '{"week":45,"month":7}'
Map, Set ์ง๋ ฌํ
์์์ ์๊ฐํ JSON.stringify
๋ฉ์๋์ replacer ํจ์๋ฅผ ์ด์ฉํ๋ฉด Map/Set๋ ์ฝ๊ฒ ์ง๋ ฌํํ ์ ์๋ค.
function replacer(key, value) {
// Map์ ์ผ๋ฐ ๊ฐ์ฒด๋ก ๋ณํ
if (value instanceof Map) return Object.fromEntries(value);
// Set์ ์ผ๋ฐ ๊ฐ์ฒด๋ก ๋ณํ
if (value instanceof Set) return Array.from(value);
return value;
}
const obj = { set: new Set([1, 2]), map: new Map([['smith', 30]]) };
JSON.stringify(obj, replacer); // '{"set":[1,2],"map":{"smith":30}}'
Map, Set ์ญ์ง๋ ฌํ
JSON.parse(text[, reviver])
์ญ์ง๋ ฌํ๋ JSON.parse
๋ฉ์๋๋ฅผ ์ด์ฉํ๋ค. JSON.parse
๋ ๋๋ฒ์งธ ์ธ์๋ก reviver ํจ์๋ฅผ ๋ฐ์ ์ ์์ผ๋ฉฐ, value ๊ฐ์ ๋ณํํ๊ฑฐ๋ ํน์ ์์ฑ์ ์ ์ธํ ๋ ์ฌ์ฉํ๋ค.
์๋ ๋ฐฉ์์ JSON.stringify
๋ฉ์๋์ replacer ํจ์์ ์ ์ฌํ์ง๋ง, reviver ํจ์๋ ๊ฐ key-value ์์ ๋จผ์ ์ํํ๊ณ , ๋ง์ง๋ง ์ํ์์ ์ต์ข
์ ์ผ๋ก ๋ณํ๋ ๊ฐ์ฒด๊ฐ value๋ก ์ ๋ฌ๋๋ค.
function reviver(key, value) {
console.log('key:', key, '|', 'value:', value);
return value;
}
JSON.parse('{"name":"smith"}', reviver);
// [์ํ1] key: 'name', value: 'smith'
// [์ํ2] key: '', value: {name: 'smith'}
// [๊ฒฐ๊ณผ] {name: 'smith'}
reviver ํจ์๋ฅผ ์ด์ฉํ๋ฉด ์ง๋ ฌํ๋ Map/Set์ ์ญ์ง๋ ฌํํ ์ ์๋ค. ํ์ง๋ง ์๋ ์ฝ๋์์ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ Map์ผ๋ก ๋ฐํํ๊ณ ์๋ค. object ํ์ ์ value๋ฅผ Map์ผ๋ก ๋ณํ์ํค๋ ์กฐ๊ฑด ๋๋ฌธ์ ๊ทธ๋ฐ๊ฒ.
function reviver(key, value) {
console.log('key:', key, '|', 'value:', value);
if (Array.isArray(value)) {
return new Set(value);
}
if (value && typeof value === 'object') {
return new Map(Object.entries(value));
}
return value;
}
const obj = { set: new Set([1, 2]), map: new Map([['smith', 30]]) };
const jsonString = JSON.stringify(obj, replacer); // '{"set":[1,2],"map":{"smith":30}}'
JSON.parse(jsonString, reviver);
// [์ํ1] key: 0 | value: 1
// [์ํ2] key: 1 | value: 2
// [์ํ3] key: set | value: [1, 2] -> Set์ผ๋ก ๋ณํ
// [์ํ4] key: smith | value: 30
// [์ํ5] key: map | value: {smith: 30} -> Map์ผ๋ก ๋ณํ
// [์ํ6] key: '' | value: {set: Set(2), map: Map(1)} -> Map์ผ๋ก ๋ณํ
// [๊ฒฐ๊ณผ] Map(2) {'set' => Set(2), 'map' => Map(1)}
์ผ๋ฐ ๊ฐ์ฒด์ Map/Set์ ๊ตฌ๋ณํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ผ๋ฏ๋ก __type
์์ ํ๋กํผํฐ๋ฅผ ๋ง๋ค์ด์ ํด๊ฒฐํ ์ ์๋ค.
function replacer(key, value) {
if (value instanceof Map) {
return { __type: 'Map', value: Object.fromEntries(value) };
}
if (value instanceof Set) {
return { __type: 'Set', value: Array.from(value) };
}
return value;
}
function reviver(key, value) {
if (value?.__type === 'Set') {
return new Set(value.value);
}
if (value?.__type === 'Map') {
return new Map(Object.entries(value.value));
}
return value;
}
const obj = { set: new Set([1, 2]), map: new Map([['smith', 30]]) };
const jsonString = JSON.stringify(obj, replacer); // '{"set":{"__type":"Set","value":[1,2]},"map":{"__type":"Map","value":{"smith":30}}}'
JSON.parse(jsonString, reviver); // {set: Set(2), map: Map(1)}
๋ ํผ๋ฐ์ค
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JS] ํจ์ํ / ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ฎ์ ๊ผด (0) | 2024.05.19 |
---|---|
[TS] TypeScript ํ์ ์คํฌ๋ฆฝํธ Infer ํค์๋ ํ์ฉํ๊ธฐ (0) | 2024.05.19 |
[CS] ๋๊ธฐ / ๋น๋๊ธฐ, ๋ธ๋กํน / ๋ ผ๋ธ๋กํน (0) | 2024.05.18 |
[JS] ์ ๊ท์์ ๊ทธ๋ฃนํ(Grouping) / ์บก์ฒํ(Capturing) ํ์ฉํ๊ธฐ (0) | 2024.05.18 |
[React] ๋์์ ํจ๊ณผ Algebraic Effect (0) | 2024.05.18 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[JS] ํจ์ํ / ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ฎ์ ๊ผด
[JS] ํจ์ํ / ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๋ฎ์ ๊ผด
2024.05.19 -
[TS] TypeScript ํ์ ์คํฌ๋ฆฝํธ Infer ํค์๋ ํ์ฉํ๊ธฐ
[TS] TypeScript ํ์ ์คํฌ๋ฆฝํธ Infer ํค์๋ ํ์ฉํ๊ธฐ
2024.05.19 -
[CS] ๋๊ธฐ / ๋น๋๊ธฐ, ๋ธ๋กํน / ๋ ผ๋ธ๋กํน
[CS] ๋๊ธฐ / ๋น๋๊ธฐ, ๋ธ๋กํน / ๋ ผ๋ธ๋กํน
2024.05.18 -
[JS] ์ ๊ท์์ ๊ทธ๋ฃนํ(Grouping) / ์บก์ฒํ(Capturing) ํ์ฉํ๊ธฐ
[JS] ์ ๊ท์์ ๊ทธ๋ฃนํ(Grouping) / ์บก์ฒํ(Capturing) ํ์ฉํ๊ธฐ
2024.05.18