Objects (๊ฐ์ฒด) โ
๊ฐ์ฒด๋ ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์กฐํํ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ธฐ๋ณธ ๋จ์๋ค. ์๋ ๊ฐ์ด๋๋ ์ผ๊ด๋ ์ ์ธ ๋ฐฉ์๊ณผ ์์ ํ ์ ๊ทผ์ ํตํด ๊ฐ์ฒด๋ฅผ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ์์ธก ๊ฐ๋ฅํ๊ฒ ์ ์งํ๋๋ก ๊ถ์ฅํ๋ค.
๐งฉ Note
๊ฐ์ฒด์ ํํ, ์์ฑ ๋ฐฉ์, ๋ณํ ๋ฐฉ์์ ์ผ๊ด๋ ํจํด์ผ๋ก ์ ์งํ๊ธฐ.
๊ฐ์ฒด๋ฅผ ๋ค๋ฃฐ ๋๋ ์ผ๊ด์ฑ๊ณผ ๋ถ๋ณ์ฑ์ ์ง์ผ์ผ ํ๋ค.
1. ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ ๋ฆฌํฐ๋ด ๋ฌธ๋ฒ์ ์ฌ์ฉ โ
eslint: no-new-object
// bad
const item = new Object();
// good
const item = {};
new Object()
๋ณด๋ค,{}
๋ฆฌํฐ๋ด์ด ์ง๊ด์ ์ด๋ค.
2. ๋์ ์์ฑ์ ๊ฐ๋ ๊ฐ์ฒด๋ ๊ณ์ฐ๋ ์์ฑ๋ช
์ ์ฌ์ฉ โ
function getKey(k) {
return `a key named ${k}`;
}
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true; // ๋์ค์ 'enabled'๋ผ๋ ๋์ ํค๋ฅผ ์ถ๊ฐ
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true, // ๊ณ์ฐ๋ ์์ฑ
};
- ๊ฐ์ฒด์ ๋ชจ๋ ์์ฑ์ ํ ๊ณณ์์ ์ ์ํ ์ ์๋ค.
- ๊ตฌ์กฐ๋ฅผ ํ์ ํ๊ธฐ ์ฝ๊ณ ์ ์ง๋ณด์๊ฐ ๊ฐ๋จํด์ง๋ค.
- ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ ์ ์ธ ์์ ์ ์๊ฒฐ์ํค๋ผ๋ ๋ป!
๊ตฌ๋ถ | ์ฝ๋ | ์ค๋ช |
---|---|---|
๋์ ์์ฑ ์ถ๊ฐ | obj[key] = value | ๊ฐ์ฒด๋ฅผ ๋จผ์ ๋ง๋ค๊ณ , ๋์ค์ ํค๋ฅผ ๋์ ์ผ๋ก ์ถ๊ฐํจ |
๊ณ์ฐ๋ ์์ฑ๋ช | { [key]: value } | ๊ฐ์ฒด ๋ฆฌํฐ๋ด ์์์ ๋ฐ๋ก ๋์ ํค๋ฅผ ๊ณ์ฐํด ์์ฑ์ผ๋ก ๋ง๋ฆ |
๐งฉ ๋์ ์์ฑ (Dynamic Property)
์ด๋ฏธ ๋ง๋ค์ด์ง ๊ฐ์ฒด์ ๋์ค์ ์์ฑ์ ์ถ๊ฐํ๋ ๋ฐฉ์์ด๋ค.
์ฆ, ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ ์ ์ด๋ค ํค๋ฅผ ์ธ์ง ๋ฏธ๋ฆฌ ์ ์ ์๋ค.
const keyName = 'enabled'; // ๋ณ์๋ก ํค ์ด๋ฆ์ ์ ์ฅ
const obj = {};
obj[keyName] = true; // true
- ์ฌ๊ฐ์
keyName
์ดenabled
๋ก ํ๊ฐ๋๊ธฐ ๋๋ฌธ์,obj.enabled = true
์ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ด์ง๋ง ์ฝ๋๋ฅผ ์์ฑํ ๋๋ ํค ์ด๋ฆ์ ๋ชฐ๋๋ค. ์ด์ฒ๋ผ ํค๋ฅผ ๋์ค์ ๋ณ์๋ ํจ์์ ๊ฒฐ๊ณผ๋ก ๊ฒฐ์ ํ๋ ๊ฒ์ด๋์ ์์ฑ
์ด๋ค.
๐งฉ ๊ณ์ฐ๋ ์์ฑ๋ช (computed propery name)
๊ฐ์ฒด ๋ฆฌํฐ๋ด ์์์ [๋๊ดํธ]
๋ฅผ ์ฌ์ฉํด ๋์ ํค๋ฅผ ์ ์ธ ์์ ์ ๊ณ์ฐํด ํฌํจํ๋ ๋ฌธ๋ฒ์ด๋ค.
์ฆ, ๋๊ดํธ ์์ ์์ด ํ๊ฐ๋์ด ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ด ์์ฑ๋ช
(key)์ผ๋ก ๋ค์ด๊ฐ๋ค.
const keyName = 'enabled';
const obj = {
[keyName]: true,
};
console.log(obj); // { enabled: true }
3. ๋ฉ์๋๋ ๋จ์ถ ๊ตฌ๋ฌธ์ ์ฌ์ฉ โ
eslint: object-shorthand
// bad
const atom = {
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
- ํจ์ ํค์๋๋ฅผ ์๋ตํ๋ฉด ๊ฐ๋ ์ฑ์ด ๋๊ณ ์ฝ๋๋์ด ์ค์ด๋ ๋ค.
4. ์์ฑ์ ๋จ์ถ ๊ตฌ๋ฌธ์ ์ฌ์ฉ โ
eslint: object-shorthand
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
};
// good
const obj = {
lukeSkywalker,
};
- ์ค๋ณต์ ์ค์ด๊ณ ์ ์ธ์ ๊ฐ๊ฒฐํ๊ฒ ํํํ ์ ์๋ค.
๐งฉ ์์ฑ ๋จ์ถ ๊ตฌ๋ฌธ (Property Shorthand)
๋ณ์ ์ด๋ฆ๊ณผ ๊ฐ์ฒด์ ์์ฑ ์ด๋ฆ์ด ๊ฐ์ ๋ key: key
๋์ key
๋ง ์จ๋ ๋๋ค.
- ReactProps ์ ๋ฌ ์
React ์ปดํฌ๋ํธ์์ props๋ฅผ ๋๊ธธ ๋ ์์ฃผ ๋ณผ ์ ์๋ค.
const user = {
name: "Binny",
age: 20,
};
// bad
<User name={user.name} age={user.age} />
// good
<User {...user} />
props๊ฐ ๊ฐ๊ฐ์ ๋ณ์์ผ ๊ฒฝ์ฐ
const name = "Binny";
const age = 20;
// bad
<User name={name} age={age} />
// good
<User name age />
- JSX ๋ฌธ๋ฒ์์๋ ๋์ผํ๋ค.
name={name}
โname
,age={age}
โage
- ํจ์ ๋งค๊ฐ๋ณ์๋ก ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ ๋
function logUser({ name, age }) {
console.log(name, age);
}
const name = 'Binny';
const age = 20;
// bad
logUser({ name: name, age: age });
// good
logUser({ name, age });
name
,age
๋ณ์๋ฅผ ๊ทธ๋๋ก ๊ฐ์ฒด๋ก ์ ๋ฌํ๋ค๋ ์๋ฏธ๊ฐ ๋ช ํํ๋ค.
- API ์์ฒญ์ ๋ฐ์ดํฐ ๋ด์ ๋
const title = 'Hello';
const content = 'This is a post.';
// bad
axios.post('/api/posts', {
title: title,
content: content,
});
// good
axios.post('/api/posts', {
title,
content,
});
- ์ด๋ฐ ํจํด์
fetch
,axios
,supabase
๋ฑ ๋ชจ๋ API ํต์ ์์ ํํ๊ฒ ๋ฑ์ฅํ๋ค.
- ์ํ(state) ์ ๋ฐ์ดํธ ์
const [user, setUser] = useState({ name: '', age: 0 });
function updateUser(name, age) {
// bad
setUser({ name: name, age: age });
// good
setUser({ name, age });
}
- ๊ฐ๋ ์ฑ์ด ์ข์์ง๊ณ , ๋ถํ์ํ ๋ฐ๋ณต์ด ์ฌ๋ผ์ง๋ค.
5. ๋จ์ถ ๊ตฌ๋ฌธ ์์ฑ์ ๊ฐ์ฒด ์ ์ธ์ ์์ ๋ถ๋ถ์ ๋ชจ์ผ๊ธฐ โ
const anakinSkywalker = "Anakin Skywalker";
const lukeSkywalker = "Luke Skywalker";
// bad
const obj = {
episodeOne: 1,
twoJediWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
- ๋จ์ถ ๊ตฌ๋ฌธ ์์ฑ์ ํ ๊ณณ์ ๋ชจ์ผ๋ฉด ์ด๋ค ์์ฑ์ด ์ถ์ฝ๋ ๋ณ์๋ช ์ธ์ง ๋น ๋ฅด๊ฒ ๊ตฌ๋ถํ ์ ์๋ค.
6. ์ ํจํ์ง ์์ ์๋ณ์์๋ง ๋ฐ์ดํ ์์ฑ์ ์ฌ์ฉ โ
eslint: quote-props
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
// data-blah๋ ์๋ณ์๋ก ์ธ ์ ์๋ ์ด๋ฆ, ํ์ดํ- ํฌํจ ์ ๋บ์
์ผ๋ก ์ธ์ํ๊ธฐ ๋๋ฌธ
};
- ์ฝ๋ ํ์ด๋ผ์ดํ ์ด ์ ํํด์ง๊ณ , JS ์์ง์ด ๋ ์ฝ๊ฒ ์ต์ ํํ ์ ์๋ค.
7. Object.prototype
์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ์ง ๋ง์์ค โ
eslint: no-prototype-builtins
Object.prototype ๋ฉ์๋: hasOwnProperty
, propertyIsEnumerable
, isPrototypeOf
๋ฑ๋ฑ
๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ์ง ๋ง๊ณ , Object.prototype
์์ ์์ ํ๊ฒ ๊บผ๋ด์ ํธ์ถ
// bad
console.log(object.hasOwnProperty(key));
// good
console.log(Object.prototype.hasOwnProperty.call(object, key));
// best
const has = Object.prototype.hasOwnProperty; // ๋ชจ๋ ์ค์ฝํ์์ ํ ๋ฒ ์บ์
console.log(has.call(object, key));
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));
- ์ด๋ฌํ ๋ฉ์๋๋ค์ ๊ฐ์ฒด์ ์์ฑ์ ์ํด ๊ฐ๋ ค์ง ์ ์๋ค.
hasOwnProperty
๋ฅผ ๋ฎ์ด์ธ ์๋ ์๊ณ ,Object.create(null)
์ฒ๋ผ ํ๋กํ ํ์ ์ด ์๋ ๊ฐ์ฒด๋ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
๐งฉ ์ Object.prototype
์์ ์ง์ ํธ์ถํด์ผ ํ ๊น?
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ชจ๋ ์ผ๋ฐ ๊ฐ์ฒด๋ Object.prototype
์ ์์๋ฐ๋๋ค.
์ฆ, ์ด๋ฐ ๊ฐ์ฒด๋ ๋ด๋ถ์ ์ผ๋ก๋ ์๋์ฒ๋ผ ์ฐ๊ฒฐ๋์ด ์๋ค.
const obj = { a: 1 };
// ๋ด๋ถ์ ์ผ๋ก๋ ์ด๋ ๊ฒ ๋์ํจ
obj.__proto__ === Object.prototype; // true
๊ทธ๋์ obj๋ Object.prototype
์์ ๋ฉ์๋๋ค์ ๋ฌผ๋ ค๋ฐ์์ ์ธ ์ ์๋ค.
obj.hasOwnProperty('a'); // true
- ํ์ง๋ง ํ๋กํ ํ์ ์ฒด์ธ ๋๋ฌธ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ฌธ์ 1. ๊ฐ์ฒด๊ฐ ๊ฐ์ ์ด๋ฆ์ ์์ฑ์ ๊ฐ์ง ์๋ ์๋ค.
๊ฐ์ฒด๊ฐ hasOwnProperty
๋ผ๋ ํค๋ฅผ ์ง์ ๊ฐ์ง๊ณ ์๋ค๋ฉด, ์์๋ฐ์ ๋ฉ์๋ ๋์ ๋ฎ์ด์ด ์์ฑ์ด ์ฌ์ฉ๋๋ค.
const obj = {
hasOwnProperty: false,
key: 'value',
};
obj.hasOwnProperty('key'); // TypeError: obj.hasOwnProperty is not a function
obj.hasOwnProperty
๋ ๋ ์ด์ ํจ์๊ฐ ์๋๋ค.false
๊ฐ์ผ๋ก ๋ฎ์ด์ผ๊ธฐ ๋๋ฌธ
๋ฌธ์ 2. Object.create(null)
๊ฐ์ ํ๋กํ ํ์
์ด ์๋ ๊ฐ์ฒด
const pureObj = Object.create(null);
console.log(pureObj.hasOwnProperty); // undefined
- ์ด ๊ฐ์ฒด๋
Object.prototype
์ ์์๋ฐ์ง ์๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ ๋ด์ฅ ๋ฉ์๋hasOwnProperty
๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๋๋ค. ๋ฐ๋ผ์pureObj.hasOwnProperty("x")
๋ฅผ ํธ์ถํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
๊ทธ๋์ Airbnb์ ๊ถ์ฅ ๋ฐฉ์
ํญ์ Object.prototype
์์ ์ง์ ๊ฐ์ ธ์ ์จ๋ผ!
Object.prototype.hasOwnProperty.call(obj, 'key');
- ์ด๋ ๊ฒ ํ๋ฉด,
obj
๊ฐ ์ด๋ค ๊ตฌ์กฐ์ด๋ ํญ์ ์๋ Object์ ์ ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค.
๋ ์์ ํ ํจํด: ์บ์ or ์ธ๋ถ ๋ชจ๋ ์ฌ์ฉ
๋ฐ๋ณต ํธ์ถ์ ์ค์ด๊ธฐ ์ํด ์ด๋ ๊ฒ ์บ์๋ฅผ ๊ถ์ฅํ๋ค.
const has = Object.prototype.hasOwnProperty;
if (has.call(obj, 'key')) {
console.log('์กด์ฌํจ');
}
๋๋ ์์ ๊ฒ์ฆ๋ NPM ํจํค์ง๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์๋ค.
import has from 'has';
if (has(obj, 'key')) {
console.log('์์ ํ๊ฒ ๊ฒ์ฌ๋จ');
}
8. ๊ฐ์ฒด ์์ ๋ณต์ฌ๋ Object.assign
๋์ ์ ๊ฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉ โ
ํน์ ์์ฑ์ด ์๋ต๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ฌ ๋๋ ๊ฐ์ฒด ๋๋จธ์ง ์ฐ์ฐ์๋ฅผ ์ฌ์ฉ.
eslint: prefer-object-spread
// ๐ very bad
// Object.assign(target, source)๋ ์ฒซ ๋ฒ์งธ ์ธ์(target)๋ฅผ ๋ณํํ๋ค.
// ์ฆ, ๋ณต์ฌ๋ณธ์ด ์๋๋ผ ์๋ณธ ์์ฒด๊ฐ ์์ ๋๋ค.
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // ์๋ณธ ๋ณํ
console.log(original); // { a: 1, b: 2, c: 3 }
// delete๋ ์ฌ๊ธฐ์ "๋ณต์ฌ๋ณธ์ ์์ ํ๋ฉด ์๋ณธ๋ ๋ฐ๋๋ค"๋ ๊ฑธ ๋ณด์ฌ์ฃผ๊ธฐ ์ํ ์์
// ์ค์ ๋ก delete copy.a๋ฅผ ํ๋ฉด original.a๋ ํจ๊ป ์ฌ๋ผ์ง๋ค. ๋ถ๋ณ์ฑ ๊นจ์ง
delete copy.a;
console.log(original); // { b: 2, c: 3 }
// ๐ bad
// ์๋ณธ์ ์ ์งํ๋ ค๋ฉด ์ฒซ ๋ฒ์งธ ์ธ์๋ก ๋ฐ๋์ "๋น ๊ฐ์ฒด({})"๋ฅผ ์ ๋ฌํด์ผ ํ๋ค.
// ํ์ง๋ง ์ด ๋ฐฉ์์ ๋งค๋ฒ {}๋ฅผ ์จ์ผ ํด์ ์ฅํฉํ๊ณ , ์ค์๋ก ์์๋ฅผ ๋ฐ๊พธ๋ฉด ์๋์น ์์ ๋ฎ์ด์ฐ๊ธฐ๊ฐ ๋ฐ์
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 });
console.log(copy); // {a: 1, b: 2, c: 3}
// ๐ good
// ์ ๊ฐ ์ฐ์ฐ์(spread operator)๋ ๊ฐ์ฅ ๊ฐ๊ฒฐํ๊ณ ์ง๊ด์ ์ธ ์์ ๋ณต์ฌ ๋ฐฉ๋ฒ์ด๋ค.
// ๋ถ๋ณ์ฑ์ ์ ์งํ๋ฉด์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ค.
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 };
console.log(original); // { a: 1, b: 2 } ๐ ์๋ณธ ๊ทธ๋๋ก
console.log(copy); // { a: 1, b: 2, c: 3 } ๐ ๋ณต์ฌ ์ฑ๊ณต
// ํน์ ์์ฑ์ ์ ์ธํ๊ณ ๋ณต์ฌํ๊ณ ์ถ๋ค๋ฉด "๋๋จธ์ง ์ฐ์ฐ์(rest operator)"๋ฅผ ์ฌ์ฉํ๋ค.
// ์ด ๋ฐฉ์์ delete๋ณด๋ค ํจ์ฌ ์์ ํ๊ณ , ๋ถ๋ณ์ฑ๋ ์งํจ๋ค.
const { a, ...noA } = copy; // a๋ฅผ ์ ์ธํ๊ณ ๋๋จธ์ง๋ฅผ ๋ณต์ฌ
console.log(noA); // { b: 2, c: 3 }
- ์ ๊ฐ ์ฐ์ฐ์๋ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ๋ฉฐ, ์๋ณธ ๊ฐ์ฒด๋ฅผ ๋ณํํ์ง ์๋๋ค.
Object.assign
๋ณด๋ค ๊ฐ๋ ์ฑ์ด ์ข๊ณ ์๋ฌ๋ฅผ ์๋ฐฉํ๋ค.
๊ท์น | ํต์ฌ ์์น | Airbnb์ ์๋ |
---|---|---|
1. ๋ฆฌํฐ๋ด ๋ฌธ๋ฒ ์ฌ์ฉ | {} ๊ฐ new Object() ๋ณด๋ค ๋ช
ํํ๊ณ ์งง๋ค | ์์ฑ ์ผ๊ด์ฑ |
2. ๊ณ์ฐ๋ ์์ฑ๋ช | ๊ฐ์ฒด๋ฅผ ์ ์ธ ์์ ์ ์๊ฒฐ | ์ ์ง๋ณด์์ฑ |
3. ๋ฉ์๋ ๋จ์ถ ๊ตฌ๋ฌธ | function ์ ๊ฑฐ๋ก ๊ฐ๋
์ฑ ํฅ์ | ์ฝ๋ ๊ฐ๊ฒฐํ |
4. ์์ฑ ๋จ์ถ ๊ตฌ๋ฌธ | key: key โ key | ์ค๋ณต ์ ๊ฑฐ |
5. ๋จ์ถ ์์ฑ ๋ชจ์ผ๊ธฐ | ์๊ฐ์ ๊ทธ๋ฃนํ | ๊ตฌ์กฐ ๋ช ํ์ฑ |
6. ๋ฐ์ดํ ์์ฑ | ์ ํจํ์ง ์์ ์๋ณ์๋ง ์ฌ์ฉ | ์ผ๊ด์ฑ, ์ต์ ํ |
7. Object.prototype ํธ์ถ | ์๋ณธ์์ ์์ ํ๊ฒ ์ ๊ทผ | ์์ ์ฑ, ๋ณด์ |
8. Object.assign ๋์ Spread | ๋ถ๋ณ์ฑ ์ ์ง, ์ฝ๋ ๊ฐ๊ฒฐํ | ๊ฐ๋ ์ฑ, ์ ์ง๋ณด์์ฑ |