배열의 요소를 하나씩 살펴보면서,
반복적인 동작을 할 때 for...of문을 사용한다고 했다.
// forEach와 map
const members = ["행섭", "스기따라", "양천", "힝카인"];
for (let member of members) {
console.log(`${member}님이 접속하였습니다.`);
}
그런데 배열에는 for of문 처럼
각 요소를 하나씩 살펴보면서 반복적인 동작을 할 수 있는 forEach와 map 메소드가 존재한다.
배열만의 메소드인 forEach와 map을 살펴보자.
forEach 메소드
// forEach와 map
const members = ["행섭", "스기따라", "양천", "힝카인"];
for (let member of members) {
console.log(`${member}님이 접속하였습니다.`);
}
console.log(`-------------------------------------`);
members.forEach(function (member) {
console.log(`${member}님이 접속하였습니다.`);
});
forEach 메소드는 메소드를 호출할 때 아규먼트로 콜백 함수를 작성해 주면
콜백 함수의 첫 번째 파라미터로 배열의 요소를 하나씩 전달하면서
매번 함수를 실행하는 원리로 동작한다.
그래서 콜백 함수에는 파라미터가 하나 이상 반드시 작성되어야 하는데
for of문과 비교하면 of 앞에 선언한 (let member) 변수와 역할이 똑같다고 볼 수 있다.
그리고 콜백 함수는 아래와 같이 Arrow Function. 즉 화살표 함수로도 작성할 수 있다.
members.forEach(function (member) {
console.log(`${member}님이 접속하였습니다.`);
});
console.log(`-------------------------------------`);
members.forEach((member) => {
console.log(`${member}님이 접속하였습니다.`);
});
forEach 메소드 - 두 번째 파라미터 (요소의 index)
forEach 메소드는 콜백 함수에서 추가적으로 다룰 수 있는 두 가지 파라미터가 더 존재하며
말했다시피, 첫 번째 파라미터는 배열의 요소가 전달되기 때문에 반드시 있어야 하고
두 번째 파라미터는 요소의 index를 관리한다.
// forEach의 파라미터들
const members = ["행섭", "스기따라", "양천", "힝카인"];
members.forEach((member, i) => {
console.log(`${i} ${member}님이 접속하였습니다.`);
});
두 번째 파라미터에 주로 i라고 많이쓰며
이 요소의 index를 콘솔에 출력해보면
각 요소의 인덱스가 다음과 같이 출력되는 것을 확인할 수 있다.
또한 index는 다른 배열과 함께 활용할 때
아래처럼 같은 index의 요소를 매칭할 때도 응용할 수 있다.
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
firstName.forEach((firstName, i) => {
console.log(`${lastName[i]}${firstName}님 환영합니다.`);
});
forEach 메소드 - 세 번째 파라미터 (array)
const firstName2 = ["형섭", "명섭", "민섭", "지섭"];
const lastName2 = ["윤", "융", "용", "영"];
firstName.forEach((firstName2, i, arr) => {
console.log(`${lastName2[i]}${firstName2}님 환영합니다.`);
console.log(arr);
});
마지막 세 번째 파라미터에는 반복 중인 배열 자체가 전달된다.
주로 arr라고 많이쓰며
배열을 콘솔에 출력해보면 다음과 같다.
forEach 메소드를 호출한 배열이 전달된 모습을 확인할 수 있는데
이렇게 변수에 담긴 배열의 경우에는 그냥 변수 이름을 그대로 사용하면 되기 때문에
일반적으로는 잘 사용되지 않는 파라미터이다.
만약,
const firstName2 = ["형섭", "명섭", "민섭", "지섭"];
const lastName2 = ["윤", "융", "용", "영"];
["형섭", "명섭", "민섭", "지섭"].forEach((firstName2, i, arr) => {
console.log(`${lastName2[i]}${firstName2}님 환영합니다.`);
console.log(arr);
});
위와 같이 변수에 담지 않고
배열값 자체에 forEach 메소드를 활용하는 경우에는
상황에 따라서 콜백 함수 내에 배열이 필요할 때 활용할 수 있다. 참고만 하자.
map() 메소드
map 메소드는 forEach와 동작하는 빙식이 거의 비슷하다.
아래와 같이 forEach에서 map으로만 바꿔도 똑같이 동작한다.
// forEach와 map
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
firstName.map((firstName, i, arr) => {
console.log(`${lastName[i]}${firstName}님 환영합니다.`);
console.log(arr);
});
여기서 포인트는 forEach와 map의 차이점이며
map은 메소드의 호출 결과로 새로운 배열을 리턴한다.
한번 예시 코드를 살펴보자.
// forEach와 map
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
firstName.map((firstName, i) => {
return lastName[i] + firstName;
});
map 메소드는 위와 같이 콜백 함수 내에서 리턴문을 작성해주면
각각의 리턴값으로 구성된 새로운 배열이 메소드의 결과로 리턴된다.
// forEach와 map
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
const fullNames = firstName.map((firstName, i) => {
return lastName[i] + firstName;
});
console.log(fullNames);
그래서 메소드를 호출한 결과를 변수에 담아서 콘솔에 출력해보면
map 메소드를 호출할 때 작성한
콜백 함수의 리턴값들로 구성된 배열이 출력된 것을 확인할 수 있다.
참고로 이 부분은 화살표 함수의 문법을 활용해서
다음과 같이 간결하게 작성할 수 있다.
/*
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
const fullNames = firstName.map((firstName, i) => {
return lastName[i] + firstName;
});
console.log(fullNames);
*/
// 화살표 함수 활용
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
const fullNames = firstName.map((firstName, i) => lastName[i] + firstName);
console.log(fullNames);
forEach문은 리턴값이 없기 때문에
변수에 담았을 땐 아래와 같이 항상 undefined 값을 가진다.
const firstName = ["형섭", "명섭", "민섭", "지섭"];
const lastName = ["윤", "융", "용", "영"];
// const fullNames = firstName.map((firstName, i) => lastName[i] + firstName);
const fullNames = firstName.forEach((firstName, i) => lastName[i] + firstName);
console.log(fullNames);
그래서 단순히 배열의 반복 작업이 필요할 때에는 forEach를 사용하고
반복 작업을 통해서 새로운 배열이 필요할 때에는 map 메소드를 활용한다.
forEach와 map 사용 시 주의할 점
forEach와 map 두 메소드의 최대 반복 횟수는
처음 호출할 때 그 당시 요소의 개수이다.
const members = ["행섭", "양천", "스기따라", "힝카인"];
members.forEach((member) => {
console.log(`${member}님이 접속하였습니다.`);
members.push("섭이");
});
console.log(members);
위와 같이 forEach나 map 메소드도 마찬가지로
콜백 함수 내부에서 반복중인 배열을 편집할 수 있다.
매번 반복할 때마다 배열의 새로운 요소를 push로 추가하게 되면
무한 루프에 빠지는 것이 아닌
딱 네 번만 동작하고 프로그램이 종료되며
그 결과로 '섭이' 문자열이 네 번 추가 된 것도 확인할 수 있다.
그러니까 forEach는 처음 members의 길이만큼만 루프 동작하는데
members.push('섭이')가 4번 실행되니까
기존 members배열에 '섭이'라는 element 4개가 추가된다.
쉽게 설명하기위해 코드를 보면 행섭, 양천, 스기따라, 힝카인 총 4개의 배열이므로
forEach 문이 총 네 번을 돌면서 한 배열씩 출력하고
하나씩 출력될 때마다 가장 마지막 부분에 '섭이'를 추가한다.
풀어쓰지면 다음과 같다.
1회
행섭 입장 / 행섭,양천,스기따라,힝카인,섭이(추가)
2회
양천 입장 / 행섭,양천,스기따라,힝카인,섭이,섭이(추가)
3회
스기따라 입장 / 행섭,양천,스기따라,힝카인,섭이,섭이,섭이(추가)
4회
힝카인 입장 / 행섭,양천,스기따라,힝카인,섭이,섭이,섭이,섭이(추가)
마지막 console.log(members);에서 추가된 '섭이' 까지 모두 출력되므로,
최종 출력 결과는 "행섭, 양천, 스기따라, 힝카인, 섭이, 섭이, 섭이, 섭이" 이다.
또한 pop() 메소드로 반복 중에 배열의 길이가 줄어드는 경우에는
반복 횟수도 함께 줄어든다.
const members = ["행섭", "양천", "스기따라", "힝카인"];
members.forEach((member) => {
console.log(`${member}님이 접속하였습니다.`);
members.pop("섭이");
});
console.log(members);
코드를 살펴보자면
처음에 "행섭, 양천, 스기따라, 힝카인" 이렇게 forEach가 시작하고
"행섭님이 입장하셨습니다"라는 콘솔이 찍힌 다음
pop 메소드로 인해 마지막 값인 "힝카인"이 삭제 된다.
그리고 나서 members는 "행섭, 양천, 스기따라" 이렇게 세 배열이 되어
"양천님이 입장하셨습니다" 라는 콘솔이 찍히고
또다시 pop 메소드로 인해 마지막 값인 "스기따라"가 삭제된다.
그러면 members는 "행섭, 양천" 만 남게되어
forEach는 더이상 돌지 않고 마지막에 members를 이 두 배열만 출력하고
프로그램은 종료된다.
이런식으로 배열의 길이가 줄어들 때 반복 횟수도 같이 줄어든다.
▶ Notion
https://purrfect-gargoyle-935.notion.site/forEach-158e9530b3e180cd91e7f12252fa9fa7?pvs=4
https://purrfect-gargoyle-935.notion.site/map-158e9530b3e18073bbdac283e21943f7?pvs=4
'JS' 카테고리의 다른 글
(26) Modern JavaScript - 배열 메소드 : some, every (0) | 2024.12.11 |
---|---|
(25) Modern JavaScript - 배열 메소드 : filter, find (0) | 2024.12.11 |
모던 자바스크립트 (15) ~ (23) 정리 (0) | 2024.12.09 |
(23) Modern JavaScript - try...catch 문 (0) | 2024.12.09 |
(22) Modern JavaScript - 에러 객체 (0) | 2024.12.06 |