Arrays (๋ฐฐ์ด) โ
๋ฐฐ์ด์ ๋ฐ์ดํฐ์ ์์๋ฅผ ์ ์งํ๋ฉฐ ์ ์ฅํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ค.
Airbnb ์คํ์ผ ๊ฐ์ด๋์์๋ ๋ช
ํํ ์์ฑ ๋ฐฉ์๊ณผ ๋ถํ์ํ ์ค๊ฐ ๋ฐฐ์ด ๋ฐฉ์ง, ๊ทธ๋ฆฌ๊ณ ์ผ๊ด๋ ์ํ ํจํด์ ๊ถ์ฅํ๋ค.
๐งฉ Note
๋ฐฐ์ด์ ๋ฐ์ดํฐ๋ฅผ ์์๋๋ก ๋ค๋ฃจ๋ ๊ฐ์ฅ ๋จ์ํ์ง๋ง ๊ฐ๋ ฅํ ๊ตฌ์กฐ๋ค.
Airbnb ๊ฐ์ด๋๋ ๋ฐฐ์ด์ ์์ฑยท๋ณต์ฌยท๋ณํ ๋ฐฉ์์ ๋ช
ํํ ์ ์ํด, ์ฝ๋์ ์์ธก ๊ฐ๋ฅ์ฑ๊ณผ ๋ถ๋ณ์ฑ์ ๋์ด๋ ๋ฐ ๋ชฉ์ ์ด ์๋ค.
1. ๋ฐฐ์ด์ ์์ฑํ ๋๋ ๋ฆฌํฐ๋ด ๊ตฌ๋ฌธ์ ์ฌ์ฉ โ
eslint: no-array-constructor
// bad
const items = new Array();
// good
const items = [];
๐ก new Array()
๋ ์ธ์์ ๊ฐ์์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์ํด ํผ๋์ ์ ๋ฐํ๋ค.
๋ฐ๋ฉด []
๋ ํญ์ ๋ช
ํํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฅํ๋ค.
new Array(3); // [ <3 empty items> ]
new Array(1, 2, 3); // [1, 2, 3]
2. ๋ฐฐ์ด์ ๊ฐ์ ์ถ๊ฐํ ๋๋ ์ง์ ์ธ๋ฑ์ค ํ ๋น ๋์ push()
์ฌ์ฉ โ
const someStack = [];
// bad
someStack[someStack.length] = 'abracadabra';
// good
someStack.push('abracadabra');
push
๋ ์๋๋ฅผ ๋ช ํํ ํํํ๊ณ , ํ์ ์ ์๋ฏธ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ ํ ์ ์๋ค.
3. ๋ฐฐ์ด์ ๋ณต์ฌํ ๋๋ ์ ๊ฐ ์ฐ์ฐ์ ...
๋ฅผ ์ฌ์ฉ โ
// ์๋ณธ ๋ฐฐ์ด
const items = ['apple', 'banana', 'cherry'];
// bad
const len = items.length; // ์๋ณธ ๋ฐฐ์ด์ ๊ธธ์ด ์ ์ฅ
const itemsCopy = []; // ๋ณต์ฌ๋ณธ์ ๋ด์ ๋น ๋ฐฐ์ด
let i;
for (i = 0; i < len; i += 1) {
itemsCopy[i] = items[i]; // ์๋ณธ์ ๊ฐ ์์๋ฅผ ํ๋์ฉ ์ ๋ฐฐ์ด์ ๋ณต์ฌ
}
console.log(itemsCopy); // ['apple', 'banana', 'cherry']
// good
// ์ ๊ฐ ์ฐ์ฐ์๋ ์ ๊ณผ์ ์ ํ ์ค๋ก ๋จ์ถ์ํด
const itemsCopy = [...items];
console.log(itemsCopy); // ['apple', 'banana', 'cherry']
- bad:
์ง์ ์ธ๋ฑ์ค๋ฅผ ๊ด๋ฆฌํด์ผ ํ๊ณ , ์๋(๋ณต์ฌ)๊ฐ ์ฝ๋๋ง ๋ณด๊ณ ๋ฐ๋ก ๋๋ฌ๋์ง ์๋๋ค. (์ ์ง๋ณด์์ฑ โ, ๊ฐ๋ ์ฑ โ) - good:
๋ด๋ถ์ ์ผ๋ก๋for
๋ฌธ์ฒ๋ผ ์ํํ์ง๋ง, ์ฝ๋๋ ๋จ ํ ์ค์ด๊ณ , ์๋๊ฐ ๋ฐฐ์ด ๋ณต์ฌ๋ผ๋ ๊ฒ ๋ฐ๋ก ์ฝํ๋ค.
4. ์ํ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํํ ๋๋ Array.from
๋์ ...
์ผ๋ก ๋ฐฐ์ด๋ก ๋ณํ โ
// NodeList ์์ฑ
const foo = document.querySelectorAll('.foo');
// good
const nodes = Array.from(foo);
// best
const nodes = [...foo];
- DOM NodeList, Set, Map ๊ฐ์
์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด
๋ ์ ๊ฐ๋ก ์ฝ๊ฒ ๋ฐฐ์ดํ ๊ฐ๋ฅํ๋ค. Array.from()
๋ณด๋ค[...foo]
๊ฐ ์ง๊ด์ ์ด๋ฉฐ, ๊ฐ๋ ์ฑ์ด ๋๋ค.[...foo]
๋ ๋จ์ํ ํผ์ณ ๋ด๋๋ค๊ฐ ์๋๋ผ, ๋ด๋ถ์ ์ผ๋ก ์ดํฐ๋ ์ดํฐ ํ๋กํ ์ฝ(Symbol.iterator)
์ ํธ์ถํด ๋ชจ๋ ์์๋ฅผ ์ํํ๋ฉฐ ์ ๋ฐฐ์ด์ ๊ตฌ์ฑํ๋ ๋ฌธ๋ฒ์ ๋จ์ถํ์ด๋ค.
๐งฉ iterable ๊ฐ์ฒด
์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ ๋ฐ๋ณต ๊ฐ๋ฅํ ๊ฐ์ฒด, ์ฆ for-of
๋ฌธ์ด๋ ์ ๊ฐ ์ฐ์ฐ์...
๋ก ์ํํ ์ ์๋ ๊ฐ์ฒด๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์๋ ์๋ ์๋ฃํ๋ค์ด ๊ธฐ๋ณธ์ ์ผ๋ก ์ดํฐ๋ฌ๋ธ์ด๋ค.
๊ตฌ๋ถ | ์์ | ์ค๋ช |
---|---|---|
Array | [1, 2, 3] | ์ํ ๊ฐ๋ฅ |
String | "hello" | ๋ฌธ์ ๋จ์๋ก ์ํ ๊ฐ๋ฅ |
Map | new Map() | ํค-๊ฐ ์ ์ํ ๊ฐ๋ฅ |
Set | new Set() | ์ค๋ณต ์๋ ๊ฐ ์ํ ๊ฐ๋ฅ |
NodeList | document.querySelectorAll('.foo') | DOM ๋ ธ๋ ์งํฉ |
TypedArray | new Uint8Array([1,2,3]) | ๋ฐฐ์ด์ฒ๋ผ ์ํ ๊ฐ๋ฅ |
์ฆ, ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ ๋ฐ๋ณต ๊ท์น์ ์ ์ํ ํน๋ณํ ๋ฉ์๋ Symbol.iterator
๋ฅผ ๋ด๋ถ์ ๊ฐ์ง๊ณ ์์ด์, ์ ๊ฐ๋ for-of
๋ฅผ ํตํด ํ๋์ฉ ๊บผ๋ผ ์ ์๋ ๊ตฌ์กฐ๋ค.
1. NodeList๋ ๋ฐฐ์ด์ด ์๋๋ค.
์ด ์ฝ๋์์ document.querySelectorAll('.foo')
๋ NodeList๋ผ๋ ํ์
์ ๋ฐํํ๋ค.
<div class="foo">A</div>
<div class="foo">B</div>
<div class="foo">C</div>
const foo = document.querySelectorAll('.foo');
console.log(foo); // NodeList(3) [div.foo, div.foo, div.foo]
console.log(foo[0]); // <div class="foo">A</div>
console.log(foo.length); // 3
NodeList๋ ๋ฐฐ์ด์ฒ๋ผ ๋ณด์ด์ง๋ง ๋ฐฐ์ด์ด ์๋๋ค.
์ฆ,
map()
,filter()
๊ฐ์ ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ง์ ์ธ ์ ์๋ค. ์ง์ง ๋ฐฐ์ด์ด ์๋๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด์ ๋ฉ์๋๋ฅผ ์์๋ฐ์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.jsfoo.map((el) => el.textContent); // TypeError: foo.map is not a function
ํ์ง๋ง ์ดํฐ๋ฌ๋ธ์ด๋ผ์, ๋ฐ๋ณต์ ๊ฐ๋ฅํ๋ค.
js// NodeList๊ฐ ์ดํฐ๋ฌ๋ธ์ธ ์ด์ ๋, NodeList ๋ด๋ถ์๋ ํน๋ณํ ์์ฑ์ด ์๋ค. // Symbol.iterator๊ฐ ์กด์ฌํ๋ค๋ ๋ป์, ์ํ ๊ท์น์ด ์์ด์ for-of๋ก ๋ฐ๋ณต ๊ฐ๋ฅํ๋ค๋ ์๋ฏธ console.log(typeof foo[Symbol.iterator]); // "function"
js// ๊ทธ๋์ ์๋ ์ฝ๋๊ฐ ๋์ํ๋ค. for (const el of foo) { console.log(el); // ๊ฐ DOM ์์ ์ถ๋ ฅ๋จ } // ๋ด๋ถ์ ์ผ๋ก๋ ์ด๋ฐ ํ๋ฆ์ด๋ค. const iterator = foo[Symbol.iterator](); console.log(iterator.next()); // { value: <div.foo>, done: false } console.log(iterator.next()); // { value: <div.foo>, done: false } console.log(iterator.next()); // { value: <div.foo>, done: false } console.log(iterator.next()); // { value: undefined, done: true }
2. ๋ณํ ๋ฐฉ๋ฒ: Array-from()
Array-from()
์ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํํ๋ ํ์ค ๋ฉ์๋์ด๋ค.
const nodes = Array.from(foo);
- ์ด์ nodes๋ ์์ ํ ๋ฐฐ์ด์ด ๋์ด์
map()
,filter()
๋ฑ์ ๋ฐ๋ก ์ธ ์ ์๋ค.
nodes.map((el) => el.textContent);
3. ๋ณํ ๋ฐฉ๋ฒ: ์ ๊ฐ ์ฐ์ฐ์...
const nodes = [...foo];
- ๋ด๋ถ์ ์ผ๋ก ๋ค์๊ณผ ๋น์ทํ๊ฒ ๋์ํ๋ค.
const nodes = [];
for (const el of foo) {
nodes.push(el);
}
- ์ฆ, ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ฅผ ํ ๋ฒ ํ์ด์ ์๋ก์ด ๋ฐฐ์ด๋ก ๋ง๋๋ ๋ฌธ๋ฒ์ด๋ค.
๐ก ๋จ์ ๋ณํ์ด๋ผ๋ฉด ์ ๊ฐ ์ฐ์ฐ์๋ฅผ ์ฐ๊ณ , Array.from()
์ map
์ฝ๋ฐฑ์ด ํ์ํ ๋๋ง ์ฐ๋ผ๋ ๋ป..! ๋ผ๊ณ ๋งํ๋ ๊ฑฐ์์.
๐งฉ ์ ๊ฐ ์ฐ์ฐ์๊ฐ ๋ด๋ถ์์ ์ค์ ๋ก ์ด๋ป๊ฒ ๋์ํ ๊น?
<div class="foo">A</div>
<div class="foo">B</div>
<div class="foo">C</div>
const foo = document.querySelectorAll('.foo');
const nodes = [...foo];
1. foo
๋ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด (NodeList)
foo = NodeList(3)[(div.foo, div.foo, div.foo)];
// ์ NodeList๋ ๋ด๋ถ์ ์ผ๋ก ์ด๋ฐ ์ดํฐ๋ฌ๋ธ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๊ณ ์๋ค.
foo[Symbol.iterator] = function () {
// ์ํ ๊ท์น ์ ์
};
- ์ฆ,
foo
๋for-of
๋ฌธ์ด๋ ์ ๊ฐ ๊ตฌ๋ฌธ์ผ๋ก ๋ฐ๋ณต ๊ฐ๋ฅํ ๊ตฌ์กฐ์์ ์ ์ธํ๊ณ ์๋ค.
2. ์ ๊ฐ ๊ตฌ๋ฌธ (...foo
)์ด ์คํ๋ ๋ ๋ด๋ถ ๋์
์์ง์ ์ค์ ๋ก ๋ค์๊ณผ ๊ฐ์ ์ผ์ ์๋์ผ๋ก ํ๋ค.
const iterator = foo[Symbol.iterator](); // โ ์ดํฐ๋ ์ดํฐ ๊ฐ์ฒด ๊บผ๋ด๊ธฐ
const resultArray = []; // โก ๊ฒฐ๊ณผ๋ฅผ ๋ด์ ์๋ก์ด ๋ฐฐ์ด ์ค๋น
let next = iterator.next(); // โข ์ฒซ ๋ฒ์งธ ๊ฐ ๊บผ๋ด๊ธฐ
while (!next.done) {
// โฃ ๋๊น์ง ๋ฐ๋ณต
resultArray.push(next.value); // โค ๊บผ๋ธ ๊ฐ ์ ์ฅ
next = iterator.next(); // โฅ ๋ค์ ๊ฐ ์์ฒญ
}
const nodes = [...foo];
// ์ฆ, ์ ์ฝ๋๋ ๋ด๋ถ์ ์ผ๋ก ์๋ ์ฝ๋์ ๋์ผํ๋ค.
const nodes = [];
for (const element of foo) {
nodes.push(element);
}
3. ๋์ ํ๋ฆ
๋จ๊ณ | ๋์ | ์ค๋ช |
---|---|---|
โ | foo[Symbol.iterator]() ํธ์ถ | ๋ฐ๋ณต์(iterator) ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ด |
โก | iterator.next() ์คํ | ์ฒซ ๋ฒ์งธ DOM ์์ ๋ฐํ |
โข | value ๋ฅผ ์ ๋ฐฐ์ด์ push | ๋ณต์ฌ ์ ์ฅ |
โฃ | done ์ด true ์ผ ๋๊น์ง ๋ฐ๋ณต | ๋ชจ๋ ์์๋ฅผ ์ํ |
โค | ์์ฑ๋ ๋ฐฐ์ด์ ๋ฐํ | ์ ๋ฐฐ์ด(nodes )์ด ๋ง๋ค์ด์ง |
4. ์ฆ, [...foo]
๋ ๋ด๋ถ์ ์ผ๋ก for-of + push()
๋ฅผ ์๋์ผ๋ก ์ํํ๋ ์งง์ ๋ฌธ๋ฒ์ด๋ค.
// ์ ํต์ ์ธ ๋ฐฉ์
const nodes = [];
for (const el of foo) {
nodes.push(el);
}
// ์ต์ ๋ฐฉ์
const nodes = [...foo];
๊ตฌ๋ถ | ์ค๋ช |
---|---|
์ดํฐ๋ฌ๋ธ | Symbol.iterator ๋ฉ์๋๋ฅผ ๊ตฌํํ ๊ฐ์ฒด |
์ ๊ฐ ์ฐ์ฐ์(...) | ์ดํฐ๋ฌ๋ธ์ ์์๋ฅผ ํ๋์ฉ ๊บผ๋ด์ ํผ์นจ |
๋ด๋ถ ๋์ | for...of ๋ฌธ์ฒ๋ผ ๋์ํ๋ฉฐ push ๋ก ์ ๋ฐฐ์ด ์์ฑ |
๊ฒฐ๊ณผ | ์์ ๋ณต์ฌ๋ ์ ๋ฐฐ์ด์ด ๋ง๋ค์ด์ง |
5. ์ ์ฌ ๋ฐฐ์ด(Array-like) ๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด๋ก ๋ณํํ ๋๋ Array.from์ ์ฌ์ฉ โ
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
// bad
const arr = Array.prototype.slice.call(arrLike);
// good
const arr = Array.from(arrLike);
- ์ ์ฌ ๋ฐฐ์ด์
length
์์ฑ์ ์์ง๋ง iterable์ด ์๋๋ค. - ๋ฐ๋ผ์ ์ ๊ฐ
...
๋ ์๋ํ์ง ์๊ณ ,Array.from()
์ ์ฌ์ฉํด์ผ ํ๋ค.
๐งฉ ์ ์ฌ ๋ฐฐ์ด ๊ฐ์ฒด(Array-like Object)
์ ์ฌ ๋ฐฐ์ด์ด๋ ๋ฐฐ์ด์ฒ๋ผ ์๊ฒผ์ง๋ง ์ค์ ๋ฐฐ์ด์ด ์๋ ๊ฐ์ฒด์ด๋ค.
์ฆ, index
์ length
์์ฑ์ ๊ฐ์ง๊ณ ์์ง๋ง, ๋ฐฐ์ด ๋ฉ์๋(map, filter, push ๋ฑ)๋ ์ ํ ์ฌ์ฉํ ์ ์๋ค.
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
console.log(arrLike[0]); // 'foo'
console.log(arrLike.length); // 3
console.log(Array.isArray(arrLike)); // false
์ด ๊ฐ์ฒด๋ ๋ณด๊ธฐ์ ๋ฐฐ์ด ๊ฐ์ง๋ง ์ธ๋ฑ์ค๋ก ์ ๊ทผํ ์ ์๊ณ , length
๋ ์๋ค. ์ค์ ๋ฐฐ์ด์ด ์๋๋ผ ๋จ์ํ ๊ฐ์ฒด๋ค.
1. ์ ์ด๋ฐ ๊ฐ์ฒด๊ฐ ์๊ธธ๊น?
์์ | ์ค๋ช |
---|---|
arguments | ํจ์ ๋ด๋ถ์์ ์ ๋ฌ๋ ์ธ์๋ฅผ ๋ด๋ ๋ด์ฅ ๊ฐ์ฒด |
NodeList | DOM API (document.querySelectorAll ) ๋ฐํ๊ฐ |
HTMLCollection | getElementsByClassName , children ๊ฒฐ๊ณผ |
{0: 'a', 1: 'b', length: 2} | ์ธ๋ฑ์ค์ length๋ฅผ ์ง์ ๊ตฌํํ ๊ฐ์ฒด |
์ ์ฌ ๋ฐฐ์ด์ ์ข ์ข ๋ฑ์ฅํ๋ค. ๋ฐฐ์ด์ฒ๋ผ ์๊ฒผ์ง๋ง ๋ฐฐ์ด ๋ฉ์๋๋ฅผ ์ธ ์ ์๋ค.
function showArgs() {
console.log(arguments.map); // undefined
}
showArgs('a', 'b', 'c');
2. ๋ฐฐ์ด์ฒ๋ผ ๋ณด์ด์ง๋ง ์ง์ง ๋ฐฐ์ด์ด ์๋
์ฆ, ์ด๋ฐ ๊ฐ์ฒด๋ ์ดํฐ๋ฌ๋ธ๋ ์๋๊ณ , ๋จ์ง 0๋ถํฐ length-1๊น์ง์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง ๊ฐ์ฒด์ผ ๋ฟ์ด๋ค.
๊ทธ๋์ ์ ๊ฐ ์ฐ์ฐ์๋ ๋์ํ์ง ์๋๋ค.
const arrLike = { 0: 'foo', 1: 'bar', length: 2 };
const arr = [...arrLike]; // TypeError: arrLike is not iterable
3. ๋ณํ ๋ฐฉ๋ฒ: ๊ณผ๊ฑฐ ๋ฐฉ์
// ๊ณผ๊ฑฐ์ ์ด๋ฐ ์์ผ๋ก ์ต์ง๋ก ๋ฐฐ์ด๋ก ๋ณํํ๋ค.
const arr = Array.prototype.slice.call(arrLike);
// ์๋ ์ฌ์ค์ ์ด๋ ๊ฒ ๋์ํ๋ค.
const arr = Array.prototype.slice.apply(arrLike);
slice()
๋ ์๋ ๋ฐฐ์ด์ฉ ๋ฉ์๋์ธ๋ฐ,call()
๋ก ๋ฐฐ์ด์ฒ๋ผ ์๊ธด ๊ฐ์ฒด์ ์์๋ก ๋ถ์ฌ์ ์คํํ ๊ฒ์ด๋ค.- ๋์์ ๋์ง๋ง ๊ถ์ฅํ์ง ์๋ ๋ฐฉ์์ด๋ค.
4. ๋ณํ ๋ฐฉ๋ฒ: ๊ถ์ฅ ๋ฐฉ์ Array.from()
ES6 ์ดํ๋ถํฐ ๊ถ์ฅ๋๋ ๋ฐฉ์์ด๋ค.
// ์ง์ง ๋ฐฐ์ด์ด ๋๋ค.
const arr = Array.from(arrLike);
console.log(arr); // ['foo', 'bar', 'baz']
console.log(Array.isArray(arr)); // true
map()
,filter()
,reduce()
๋ฑ ๋ฐฐ์ด ๋ฉ์๋๋ ์ ์ ์๋ํ๋ค.
Array.from()
์ ๋ ๋ฒ์งธ ์ธ์๋ก ๋งคํ ์ฝ๋ฐฑ ํจ์๋ ๋ฐ์ ์ ์๋ค.
const arr = Array.from(arrLike, (item) => item.toUpperCase());
console.log(arr); // ['FOO', 'BAR', 'BAZ']
- ์ฆ, ๋ฐฐ์ด๋ก ๋ณํํ๋ฉด์ ๋์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ ์ ์๋ค.
5. ์ ๊ฐ๊ฐ ์๋๋ ์ด์
...
์ฐ์ฐ์๋ ์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด๋ง ํผ์น ์ ์๋ค.
const arrLike = { 0: 'a', 1: 'b', length: 2 };
const arr = [...arrLike]; // TypeError
// ๋ด๋ถ์ ์ผ๋ก ์๋์ ๊ฐ์ด ๋์ํ๊ธฐ ๋๋ฌธ!
arrLike[Symbol.iterator]; // undefined
- ์ฆ,
arrLike
๋ ์ดํฐ๋ฌ๋ธ ํ๋กํ ์ฝ์ ๊ตฌํํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ ๊ฐ๊ฐ ๋ถ๊ฐ๋ฅํ๋ค.
๊ตฌ๋ถ | ์ค๋ช |
---|---|
์ ์ฌ ๋ฐฐ์ด | ์ธ๋ฑ์ค์ length๋ง ๊ฐ์ง ๊ฐ์ฒด (๋ฐฐ์ด ์๋) |
์์ | arguments , HTMLCollection , {0:'a', length:1} |
๋ฌธ์ ์ | ๋ฐฐ์ด ๋ฉ์๋ ์ฌ์ฉ ๋ถ๊ฐ, ์ ๊ฐ(... ) ๋ถ๊ฐ๋ฅ |
ํด๊ฒฐ๋ฒ (๊ณผ๊ฑฐ) | Array.prototype.slice.call(obj) |
ํด๊ฒฐ๋ฒ (ํ๋) | Array.from(obj) |
Array.from(obj, mapFn) ์ผ๋ก ๋ณํ+๋งคํ ๊ฐ๋ฅ |
์ ์ฌ ๋ฐฐ์ด์ ๋ฐฐ์ด์ฒ๋ผ ์๊ธด ๊ฐ์ฒด
์ง๋ง ์ดํฐ๋ฌ๋ธ์ด ์๋๋ค.
๋ฐ๋ผ์ ...
๋ก ํผ์น ์ ์๊ณ , Array.from()
์ ์ฌ์ฉํด์ผ ์ง์ง ๋ฐฐ์ด๋ก ๋ณํ๋๋ค.
6. ๋งคํํ ๋๋ ์ ๊ฐ ...
๋์ Array.from()
์ ์ฌ์ฉ โ
์ค๊ฐ ๋ฐฐ์ด ์์ฑ์ ๋ฐฉ์งํ๊ธฐ ๋๋ฌธ์ด๋ค.
// bad
const baz = [...foo].map(bar);
// good
const baz = Array.from(foo, bar);
Array.from()
์ ๋ ๋ฒ์งธ ์ธ์๋ก๋งคํ ์ฝ๋ฐฑ
์ ๋ฐ๋๋ค.- ๋ฐ๋ผ์
์ค๊ฐ ๋ฐฐ์ด
์ ๋ง๋ค์ง ์์ ์ฑ๋ฅ์ ์ด์ ์ด ์๋ค.
๐งฉ ์ค๊ฐ ๋ฐฐ์ด์ด๋?
...
์ ๊ฐ๋ฅผ ๋จ์ฉํด์ ๋ถํ์ํ ์ค๊ฐ ๋ฐฐ์ด์ ์์ฃผ ๋ง๋ค์ด๋ธ๋ค.
1. ์ค๊ฐ ๋ฐฐ์ด์ด๋
const baz = [...foo].map(bar);
์ ์ฝ๋๋ ๋ฌธ์ ์์ด ๋ณด์ด์ง๋ง, ๋ด๋ถ์ ์ผ๋ก ๋ ๋จ๊ณ์ ๋ฉ๋ชจ๋ฆฌ ์์ ์ด ์ผ์ด๋๋ค.
// ๋ด๋ถ์ ์ผ๋ก ์ด๋ฐ ์์ผ๋ก ๋์ํ๋ ์
์ด๋ค
const temp = [...foo]; // ์์ ๋ฐฐ์ด
const baz = temp.map(bar); // ์๋ก์ด ๋ฐฐ์ด
[...foo]
foo
(์ดํฐ๋ฌ๋ธ ๊ฐ์ฒด ๋ฑ)๋ฅผ ์ ๋ฐฐ์ด๋ก ๋ณต์ฌ โ ์์ ๋ฐฐ์ด์ด ํ ๋ฒ ๋ง๋ค์ด์ง๋ค.
.map(bar)
๊ทธ ์ ๋ฐฐ์ด์ ์ํํ๋ฉด์bar
ํจ์๋ฅผ ์ ์ฉ โ ๊ฒฐ๊ณผ ๋ฐฐ์ด์ด ๋ ๋ง๋ค์ด์ง๋ค.
์ฆ, ์ด 2๊ฐ์ ๋ฐฐ์ด์ด ์๊ธด๋ค:
foo
๋ฅผ ์ ๊ฐํด ๋ง๋ ์์ ๋ฐฐ์ดmap()
๊ฒฐ๊ณผ๋ก ๋์จ ์ ๋ฐฐ์ด
2. ํด๊ฒฐ๋ฒ: Array.from(iterable, mapFn)
Array.from()
์ ๋ ๋ฒ์งธ ์ธ์๋ก ๋งคํ ์ฝ๋ฐฑ ํจ์(mapFn)
๋ฅผ ๋ฐ์ ์ ์๋ค.
์ฆ, ๋ณํ๊ณผ ๋งคํ์ ํ ๋ฒ์ ํ ์ ์๋ค.
const baz = Array.from(foo, bar);
// ๋ด๋ถ์ ์ผ๋ก๋ ์ด๋ฐ ์๋ฏธ๋ค.
const baz = [];
for (const el of foo) {
baz.push(bar(el));
}
- ์ฆ,
foo
์ ๊ฐ ์์๋ฅผ ๋ฐ๋ก ๋ณํํด์ ์ ๋ฐฐ์ด์ ๋ฃ๋๋ค. ์ค๊ฐ ๋ฐฐ์ด์ด ์๊ธฐ์ง ์๋๋ค.
๋ ๋ฐฉ์์ ๋น๊ตํด๋ณด๋ฉด,
๊ตฌ๋ถ | ์ฝ๋ | ๋ฐฐ์ด ์์ฑ ํ์ | ๋ฉ๋ชจ๋ฆฌ ํจ์จ | ์๋ |
---|---|---|---|---|
bad | [...foo].map(bar) | 2๋ฒ (์์ + ๊ฒฐ๊ณผ) | ๋ญ๋น ๋ฐ์ | ๋๋ฆผ |
good | Array.from(foo, bar) | 1๋ฒ (๊ฒฐ๊ณผ๋ง) | ํจ์จ์ | ๋น ๋ฆ |
// ์์
const foo = new Set([1, 2, 3]);
// bad
const baz1 = [...foo].map((x) => x * 2);
// ๋ด๋ถ ๋์: [1, 2, 3] โ [2, 4, 6]
// good
const baz2 = Array.from(foo, (x) => x * 2);
// ๋ด๋ถ ๋์: ๋ฐ๋ก [2, 4, 6]
๊ฒฐ๊ณผ๋ ๊ฐ์ง๋ง,
bad
๋ฐฉ์์ ๋ถํ์ํ ์์ ๋ฐฐ์ด[1, 2, 3]
์ ๋ง๋ ๋ค.bad
๋ด๋ถ ๋์ ์์ฝfoo(Set)
๋ ์ดํฐ๋ฌ๋ธ์ด๋ฏ๋ก ์ ๊ฐ ๊ฐ๋ฅ- ์์ง์
foo
๋ฅผ ์ํํ๋ฉฐ ์ ๋ฐฐ์ด์ ์์ฑ .map()
์ด ๊ทธ ์ ๋ฐฐ์ด์ ์ํํด ๋ ๋ค๋ฅธ ๋ฐฐ์ด(baz)์ ์์ฑํ๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ์ ๋ ๊ฐ์ ๋ฐฐ์ด ๊ฐ์ฒด๊ฐ ์กด์ฌํ๊ฒ ๋๋ค.
good
๋ด๋ถ ๋์ ์์ฝArray.from
์ดfoo
์์ดํฐ๋ ์ดํฐ(Symbol.iterator)
๋ฅผ ์ฌ์ฉ- ์ํํ๋ฉด์ ๊ฐ ์์๋ฅผ
mapFn(x => x * 2)
๋ก ๋ฐ๋ก ๋ณํ - ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ๋์ ์ ๋ฐฐ์ด(baz)์ ์ง์ ๋ด์
์ค๊ฐ ๋ฐฐ์ด์ด ์๋ค!
3. Array.from()
์ ๋ ๋ฒ์งธ ์ธ์(mapFn)
์ด ์ธ์๋ Array.prototype.map()
๊ณผ ๋์ผํ๊ฒ ๋์ํ๋ค.
Array.from(arrayLike, (value, index) => {
// value: ๊ฐ ์์
// index: ์ธ๋ฑ์ค
// thisArg: ์ ํ์ ์ธ ๋ฒ์งธ ์ธ์๋ก ๋ฐ์ธ๋ฉํ ๊ฐ
});
// ์์
const doubled = Array.from({ length: 5 }, (_, i) => i * 2);
console.log(doubled); // [0, 2, 4, 6, 8]
- ์ด๋ฐ ์์ผ๋ก ๋ฐฐ์ด ์์ฑ + ๋งคํ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์๋ค.
๊ตฌ๋ถ | ์ค๋ช |
---|---|
[...] | ์ดํฐ๋ฌ๋ธ์ ๋จผ์ ๋ฐฐ์ด๋ก ๋ณต์ฌ (์์ ๋ฐฐ์ด ์์ฑ๋จ) |
.map() | ๋ณต์ฌ๋ ๋ฐฐ์ด์ ๋ค์ ๋งคํํ์ฌ ์๋ก์ด ๋ฐฐ์ด ์์ฑ |
Array.from(iterable, mapFn) | ๋ณํ๊ณผ ๋งคํ์ ํ ๋ฒ์ ์ํ |
์ฅ์ | ๋ถํ์ํ ๋ฐฐ์ด ์์ฑ ๋ฐฉ์ง โ ๋ฉ๋ชจ๋ฆฌ ํจ์จ โ, ์๋ โ |
์ ๊ฐ + map
์ ๋ณด๊ธฐ์ ๋จ์ํ์ง๋ง, ์ค์ ๋ก ์ค๊ฐ ๋ฐฐ์ด์ด ํ ๋ฒ ๋ ๋ง๋ค์ด์ ธ ์ฑ๋ฅ ๋ญ๋น๊ฐ ์๊ธด๋ค.Array.from(iterable, mapFn)
์ ๋ณํ + ๋งคํ์ ํ ๋ฒ์ ์ฒ๋ฆฌํด ํจ์จ์ ์ด๋ค.
7. ๋ฐฐ์ด ๋ฉ์๋ ์ฝ๋ฐฑ์๋ return
์ ๋ช
์ โ
eslint: array-callback-return
๋ง์ฝ ํจ์๊ฐ ๋จ์ผ ํํ์์ ๋ฐํํ๋ ๊ตฌ๋ฌธ์ด๋ผ๋ฉด return
์ ์๋ตํด๋ ๋๋ค.
// good
// ์ฌ๋ฌ ์ค ๋ธ๋ก ๋ด๋ถ์์๋ ๋ฐ๋์ return ์ฌ์ฉ
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
// good
// ๋จ์ผ ํํ์์ด๋ผ๋ฉด return ์๋ต ๊ฐ๋ฅ (์๋ฌต์ ๋ฐํ)
[1, 2, 3].map((x) => x + 1);
// bad
// return์ด ์์ผ๋ฏ๋ก reduce์ acc๊ฐ undefined๊ฐ ๋์ด๋ฒ๋ฆผ
[
[0, 1],
[2, 3],
[4, 5],
].reduce((acc, item, index) => {
const flatten = acc.concat(item); // ๊ธฐ์กด ๋ฐฐ์ด์ ํ์ฌ ๋ฐฐ์ด์ ํฉ์นจ
acc[index] = flatten; // return์ด ์์ด์ acc ๊ฐ์ด undefined๋ก ๋ณํจ
});
// good
// ๊ฐ ๋จ๊ณ๋ง๋ค ๋ฐํ๊ฐ์ ๋ช
์ํด์ผ ๋ค์ ๋ฐ๋ณต์ผ๋ก ์ ๋ฌ๋จ
[
[0, 1],
[2, 3],
[4, 5],
].reduce((acc, item, index) => {
const flatten = acc.concat(item);
acc[index] = flatten;
return flatten;
});
// bad
// else๋ฌธ์ return์ด ์์ง๋ง if ์์ชฝ์ ๋ณต์กํ๊ฒ ์ค์ฒฉ๋์ด ์ฝ๊ธฐ ์ด๋ ค์
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
} else {
return false;
}
});
// good
// early return์ผ๋ก ๊น๋ํ๊ฒ ์์ฑ
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
}
return false;
});
- ์ฝ๋ฐฑ์์
return
์ ์๋ตํ๋ฉดundefined
๊ฐ ๋ฐํ๋ผ ๋ฒ๊ทธ๋ก ์ด์ด์ง ์ ์๋ค.
8. ๋ฐฐ์ด์ด ์ฌ๋ฌ ์ค์ ๊ฑธ์ณ ์๋ค๋ฉด ๋ฐฐ์ด์ ์ฐ ์ดํ์ ๋ซ๊ธฐ ์ด์ ์ ์ค๋ฐ๊ฟ์ ์ฐ์ โ
// good
const arr = [
[0, 1],
[2, 3],
[4, 5],
];
const objectInArray = [
{
id: 1,
},
{
id: 2,
},
];
const numberInArray = [1, 2];
- ์ฌ๋ฌ ์ค์ ๊ฑธ์น ๋ฐฐ์ด์
[
์ดํ์]
์ด์ ์ ์ค๋ฐ๊ฟ์ ์ถ๊ฐํ๋ค. - ํ ์ค ๋ฐฐ์ด์
[1, 2, 3]
์ฒ๋ผ ์ ์งํ๋ค.
๊ท์น | ์์น |
---|---|
๋ฆฌํฐ๋ด ์์ฑ | [] ๋ ๋ช
ํํ๊ณ ์์ธก ๊ฐ๋ฅ |
๊ฐ ์ถ๊ฐ | push() ๋ก ์๋๋ฅผ ๋๋ฌ๋ |
๋ฐฐ์ด ๋ณต์ฌ | ...spread ๋ก ๋ถ๋ณ์ฑ ์ ์ง |
iterable ๋ณํ | ์ ๊ฐ(... ) ์ฌ์ฉ |
array-like ๋ณํ | Array.from() ์ฌ์ฉ |
๋งคํ | Array.from(obj, mapFn) |
์ฝ๋ฐฑ ๋ฐํ | return ๋ช
์ |
ํฌ๋งทํ | ์ค๋ฐ๊ฟ ๊ท์น ์ ์ง |