js array.sort()가 원본을 바꾼다

  • 가끔 원본이 바뀌어서 예상치 못한 동작을 할 때가 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
// 원본인 arr 이 정렬됨
{
const arr = [1, 2, 3];
const sortedArr = arr.sort((a, b) => b - a);
console.log(arr === sortedArr); // true
}

// 원본인 arr를 살리면서 정렬된 새 배열 얻기
{
const arr = [1, 2, 3];
const sortedArr = [...arr].sort((a, b) => b - a);
console.log(arr === sortedArr); // false
}
  • [...arr] 이런 식으로 배열을 복사할 수 있다

하나 더, 배열 복사할 때 주의할 점

  • 그런데 number[] 타입이 아니라 {...}[]같은 객체 배열이라면
  • [...arr] 연산으로 새로운 배열이 만들어지기는 하지만
  • 원소 하나하나는 여전히 call by reference 이기 때문에
  • 완전한 복사본(깊은 복사)을 얻은 게 아니라는 점을 유의해야 한다

참고

js empty array

new Array(n)으로 초기화한 배열에 array api가 동작하지 않았다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const arr = new Array(5);

console.log(arr.length, arr); // 5 [ <5 empty items> ]
console.log(arr.push(1), arr); // 6 [ <5 empty items>, 1 ]
console.log(arr.push(2), arr); // 7 [ <5 empty items>, 1, 2 ]

console.log(arr.map((v) => v * 2)); // [ <5 empty items>, 2, 4 ]

arr.forEach((v) => {
console.log(v);
});
// 1
// 2

console.log(`-----------`);

for (let index = 0; index < arr.length; index++) {
const element = arr[index];
console.log(element);
arr[index] = undefined;
}
// undefined
// undefined
// undefined
// undefined
// undefined
// 1
// 2

console.log(`-----------`);

arr.forEach((v) => {
console.log(v);
});
// undefined
// undefined
// undefined
// undefined
// undefined
// undefined
// undefined
  • 위에 map이나 forEach를 보면 array api가 초기화하지 않은 인덱스에 대해 동작하지 않는 것을 확인할 수 있다
  • 직접 for문으로 찍어보면 undefined이라 나온다
  • 그러면서 undefined으로 전부 초기화해줬다
  • 직접 초기화해주니까 array api forEach가 동작하는 것을 확인할 수 있다
  • array api를 동작하지 않는 것을 경험했다
1
const arr = new Array(5).fill(0);
  • 이런 식으로 특정 값으로 직접 초기화를 해줘야 스킵되지 않고 정상적으로 api를 사용할 수 있다

array to hashmap js

ex1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const arr = [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 },
];

let map = new Map();

arr.reduce((newMap, cur) => {
const { id, value } = cur;
newMap.set(id, value);
return newMap;
}, map);

console.log(map);
map.get(1);
  • reduce로 합쳐주는 방식으로 할 수 있고
ex2
1
2
3
4
5
6
7
8
9
const arr = [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 },
];

const map = new Map(arr.map((item) => [item.id, item.value]));

console.log(map);
  • array.map()과 Map 생성자로 짧고 이쁘게 변화해줄 수 있다

참고

forEach await 안되는 문제

상황

  • 배열로 저장되어 있는 데이터를 forEach로 순회하면서 db에 INSERT하는 쿼리를 만들려고 했다
  • 근데 비동기적으로 동작했다
1
2
3
await data.forEach(async (element: ArticlePreview, idx: number) => {
// insert query
});

해결

1
2
3
4
5
6
7
8
9
for (const element of data) {
// ...
try {
const a = await databaseConnection.query(queryString, [
// ...
]);
}
// ...
}
  • for of에서는 await을 통해서 순차적으로 처리가 가능했다

시도해보지 않은 다른 방향

참고