일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- boolean
- input
- 학습법 #집중력
- htmlFor
- const
- VAR
- appendChild
- createtextnode
- createElement
- Append
- Let
- FOR
- Openlayers
- Today
- Total
Atomic Habits
for / for-in / forEach / for-of 무엇으로 자바스크립트 리스트를 돌아야 하나 본문
출처 : https://yceffort.kr/2021/06/best-solution-for-looping-over-array
자바스크립트에서 배열을 순회하는 방법은 4가지가 있다.
- for
- for-in
- forEach
- for-of
각각의 방법을 살펴보면서, 배열을 순회하기 위한 가장 좋은 방법은 무엇인지 나름 결론을 내려본다.
for
ES1 시절부터 있었던 가장 근-본적인 방법이다.
const arr = ['a', 'b', 'c']
arr.prop = 'prop'
for (let i = 0; i < arr.length; i++) {
const e = arr[i]
console.log(i, e)
}
// 0 "a"
// 1 "b"
// 2 "c"
- 배열의 첫번째 뿐만 아니라 n번째에서 돌 수도 있음
- 단순히 배열을 순회하려는 목적에 비해서 많은 작업이 필요함 (추가적인 변수 선언 및, 증가, 길이 계산 등)
for-in
놀랍게도, for-in도 ES1부터 있었던 근-본 방식이다.
const arr = ['a', 'b', 'c']
arr.prop = 'prop'
for (const key in arr) {
console.log(key, typeof key, arr[key])
}
// 0 "string" a
// 1 "string" b
// 2 "string" c
// 3 "string" prop prop
위의 코드 실행결과에서 알 수 있듯이, for-in을 배열을 순회하는데 쓰는건 별로 좋지 못하다.
- key 값만 가져올 수 있음
- key 값의 타입에서 볼 수 있다시피, 숫자가 아니고 문자열로 나온다.
const arr = [1, 2, 3]
arr[0] === arr['0'] // true
배열은 [] 에서 숫자로도 접근할 수 있기 때문에 객체와 다르다고 생각할 수 있다. 그러나 배열 또한 객체 이므로, []안에 심볼 외의 값이 들어가면 강제로 string으로 변환한다.
- 위에서 볼 수 있는 것 처럼, 모든 enumerable한 키들을 죄다 순회한다.
따라서 for-in은 객체가 enumberable한 모든 속성을 순회할 때 사용하는 것이 좋다. 그러나 이 경우에도, 프로토타입 체인을 순회하는 것이 더 낫다.
forEach
ES5에서 추가된 새로운 방법, Array.prototype.forEach()이다.
const arr = ['a', 'b', 'c']
arr.prop = 'prop'
arr.forEach((e, index) => {
console.log(e, index)
})
// a 0
// b 1
// c 2
꽤 편리한 방법처럼 보인다. 배열의 요소와 인덱스 모두에 접근할 수 있으며, 화살표 함수를 통해서 더욱더 우아하게 코드를 짤 수 있다.
그럼에도, 아래와 같은 단점이 있다.
- await을 루프 내부에 쓸 수 없음
- forEach() 중간에 루프를 탈출하는 것이 곤란. 다른 문법의 경우엔, break로 가능
const arr = ['a', 'b', 'c']
arr.forEach((e, index) => {
console.log(e)
if (e === 'b') {
// break Illegal break statement
return
}
})
// a
// b
// c
아래와 같이 some을 사용하면 탈출할 수 있다.
const arr = ['a', 'b', 'c']
arr.some((e, index) => {
if (e === 'b') {
return true // break
}
console.log(e) // falsy한 값이기 때문에 계속 루프를 돈다.
})
그러나 이는 some을 의도대로 사용하는 것이 아니거니와, 왜 이런 코드를 짰는지 다른 사람들이 이해하기 어려울 것이다.
for-of
ES6에 나온 가장 최신 기능이다.
const arr = ['a', 'b', 'c']
arr.prop = 'prop'
for (const e of arr) {
console.log(e)
}
// a
// b
// c
- 모든 루프를 원하는 대로 순회할 수 있다.
- await을 사용한 for-await-of가 가능하다.
- break continue를 사용할 수 있다.
for-of를 활용하면, 키만 접근하거나, 혹은 키와 값 모두 접근하거나 하는 것이 모두 가능하다.
const arr = ['a', 'b', 'c']
for (const key of arr.keys()) {
console.log(key, typeof key)
}
// 0 "number"
// 1 "number"
// 2 "number"
const arr = ['a', 'b', 'c']
for (const [key, value] of arr.entries()) {
console.log(key, value)
}
// 0 "a"
// 1 "b"
// 2 "c"
const m = new Map().set(1, 1).set(2, 2).set(3, 3)
for (const [key, value] of m) {
console.log(key, value)
}
// 1 1
// 2 2
// 3 3
결론
- for-of로 다른 순회문에서 할 수 있는 모든 것을 할 수 있어서 가장 좋다.
- 성능에 대한 비교는 사실 의미가 없을 것 같다. (엄밀히 따지면 forEach가 제일 느리다.) 그러나 자바스크립트에서 성능이 유의미할 정도로 순회문을 돌아야 한다면, 웹 어셈블리 등 다른 방법을 알아보는 것이 좋다.
- 여담으로, 적어도 프론트엔드 개발에서 for-of를 돌아야 하는 일은 거의 없었던 것 같다. 대부분이 map reduce를 사용해서 해결할 수 있고, 그 쪽이 더 함수형이고 읽기도 간결하다.
'IT > JavaScript-JQuery' 카테고리의 다른 글
[Javascript] append vs appendChild 차이점 (0) | 2022.06.06 |
---|---|
[JavaScript] 깊은 복사, 얕은 복사 - 재귀함수 (0) | 2022.06.06 |
forEach, for in, for of 특징 및 성능 비교 (0) | 2022.06.01 |
[Javascript] 배열 정렬하기 (오름차순, 내림차순, 문자열, 객체) (0) | 2022.06.01 |
[HTML] script 태그는 어디에 위치 해야 할까? / defer / async (0) | 2022.05.30 |