알고리즘 문제를 풀던 중 다른 분 코드에서 foreach의 사용을 보게 되었다.
foreach의 존재는 알지만 for문이 익숙하다보니 foreach는 사용하지 않게 되었는데
이번 기회에 차이를 다시 한번 정리하며 어떤 문법을 사용하는것이 편한지 공부 하고자 한다.
for문
const wires = [[1,2],[2,3],[3,4]]
for (let i = 0; i < wires.length; i++) {
let wire = wires[i];
let node1 = wire[0];
let node2 = wire[1];
tree[node1].push(node2);
tree[node2].push(node1);
}
for (let i = 0; i < wires.length; i++) {
let wire = wires[i];
let network1 = bfs(wire[0], wire[1], tree, new Array(n + 1).fill(false));
let network2 = bfs(wire[1], wire[0], tree, new Array(n + 1).fill(false));
answer = Math.min(Math.abs(network1 - network2), answer);
}
- 가장 기본적인 반복문
- 반복 횟수가 정해져 있는 경우에 많이 사용한다.
- 중간에 "break"를 만나면 반복문을 중단
- 구조는 흔히 알고 있기 때문에 생략 ..
forEach 문
const wires = [[1,2],[2,3],[3,4]]
wires.forEach(wire => {
let node1 = wire[0];
let node2 = wire[1];
tree[node1].push(node2);
tree[node2].push(node1);
});
wires.forEach(wire => {
let network1 = bfs(wire[0], wire[1], tree, new Array(n + 1).fill(false));
let network2 = bfs(wire[1], wire[0], tree, new Array(n + 1).fill(false));
answer = Math.min(Math.abs(network1 - network2), answer);
});
- 배열 메서드
- 배열의 각 요소에 대해 callback을 실행
- 배열을 순회하므로 중간에 "break", "continue"를 사용할 수 없다.
- forEach 문은 에러가 발생해도 멈추지 않음.
- for문보다 속도가 빠르다.
- return 사용할 수 없음
- forEach문의 반환값은 undefined이기 때문에 밖으로 return 값을 줄 수 없습니다. 내부에서 수정한 값을 반환하고 싶다면 별도의 변수를 선언하고 담아야 합니다.
- forEach문의 반환값은 undefined이기 때문에 밖으로 return 값을 줄 수 없습니다. 내부에서 수정한 값을 반환하고 싶다면 별도의 변수를 선언하고 담아야 합니다.
구조
arr.forEach(callback(currentvalue[, index[, array]])[, thisArg])
// 화살표 함수
array.forEach(매개변수 => {
console.log(매개변수)
});
- currentValue 요소값
- index 인덱스
- array forEach()를 호출한 배열.
- thisArg callback을 실행할 때 this로 사용할 값
차이점
for 는 동기 방식이기 때문에 for문 안에 오류가 나면 에러 위치 아래의 이벤트들은 동작하지 않고 멈춘다.
forEach는 ES6 문법으로 콜백함수를 뿌린다. 비동기 방식으로 진행되기 때문에 forEach문 안에 에러가 발생하더라도 멈추지 않고 동작한다. 대신 원하는 순서와는 다르게 프로그램이 동작할 수 있다.
-> 결과물은 똑같이 나오는 것으로 보일 수 있지만, 동기(sync)와 비동기(async)의 차이가 있다.
성능 차이
forEach문은 "향상된 for문"이라 칭하기도 한다. 가변적인 배열이나 리스트 크기를 구할 필요가 없어 복잡한 반복문에 적합하며, 인덱스를 생성하여 접근하는 for문보다 수행속도가 더 빠르다.
-> 내장함수이기 때문
foreach 사용의 단점
(1) 반복문 내에서 배열이나 리스트 값을 변경하거나 추가할 수 없다
ㄴ 읽기 전용으로 불러오기 때문에 데이터를 수정하는 행위가 불가능하다.
(2) 배열을 역순으로 탐색할 수 없다
ㄴ 순서대로 정보를 가져오기 때문에 역순으로 가져올 방법이 없다.
map ()
- 배열 메서드
- 배열의 각 요소에 대해 callback 실행
- 배열을 순회하므로 중간에 break 문을 사용할 수 없다.
- forEach( )와 달리 실행결과를 모은 새로운 배열을 리턴 ( return 반드시 필요 )
- 반환값 설정하지 않는 경우 반환되는 배열의 요소가 'undefined'로 출력됨
const animals = ["dog", "cat"];
animals.forEach(el => {
console.log(el); // 'dog' 'cat'
});
let foo = animals.map(el => {
console.log(el); // 'dog' 'cat'
return el;
});
console.log(foo); // [ 'dog', 'cat' ]
/*
단순 반복이라면 for
배열을 순회하려면 forEach
배열을 순회 후 새 배열을 얻고 싶다면 map
*/
for-in
- Object의 key 순회
- Object의 enumerable한 key에 차례로 접근하는데 사용되는 반복문.
- for-in은 열거 가능한 값이 true로 설정되어 있어 key만 반복할 수있고 비열거형인 value에는 접근할 수 없다.
- Array에도 사용할 수 있지만 일반적으로 Object 를 제외한 객체에는 사용하지 않는 것이 좋다.
> 그렇다면 왜 for-in 문을 쓸까?
for-in은 다른 반복문으로 충분히 대체 가능한데 왜 쓰는 것일까?
키-값 쌍이 선호되는 데이터의 경우나 특정 값을 가진 key가 있는지 확인하려는 경우에는 for-in이 유용하다.
객체에 key를 가져와서 어떤 작업을 처리하는 경우에는 for-in을 쓰기 편하다고 한다.
for of
- forEach문과 달리 break, continue, return 구문과 함께 사용할 수 있다.
- iterable(반복 가능한)한 객체(Array, Map, Set, String, TypedArray, arguments 등)에 대해 value를 반복 순회한다.
- 일반 객체는 iterable하지 않기 때문에 for of를 사용하게 되면 타입에러가 뜬다.
const array = ['가', '나', '다', '라'];
array.forEach(el => {
console.log(el); // el은 배열의 요소값 👉 '가' '나' '다' '라'
})
for (let value of array) {
console.log(value); // value는 배열의 요소값 👉 '가' '나' '다' '라'
}
for (let key in array) {
console.log(key); // key는 배열의 인덱스값... 👉 '0' '1' '2' '3'
}
'JS' 카테고리의 다른 글
[js] toFixed() 메서드 (0) | 2023.02.05 |
---|---|
[JS] 배열의 순서 (sort()메서드, reverse() 메서드) (0) | 2023.02.03 |
[JS]BigInt (0) | 2023.01.31 |
[JS] == , === 차이점 (0) | 2023.01.18 |
[JS] 배열 특정 값 포함 여부(includes, indexOf, some, every) (0) | 2023.01.17 |