map은 배열의 모든 요소에 특정 로직을 적용하여 새로운 배열을 생성하는 데 사용된다. 기존 배열은 변경되지 않으며, 각 요소에 적용한 결과값을 가진 새로운 배열을 반환한다.
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map((num) => num * 2);
console.log(doubledNumbers); // [2, 4, 6, 8, 10]
위 예시에서는 map을 통해 numbers 배열의 각 요소에 2를 곱해 새로운 배열 doubledNumbers 를 생성했다. 이때 원본 배열인 numbers는 변경되지 않는다.
const MedalList = ({ results }) => {
return (
<ul>
{results.map((result) => (
<li key={result.id}>{result.country}: {result.medal} 획득 메달 수</li>
))}
</ul>
);
};
위의 코드처럼 results 배열의 map을 통해 각 요소에 대해 <li> 요소를 생성하여 국가와 금메달 수를 렌더링 할 수 있다.
forEach는 배열의 각 요소를 순회하면서 특정 작업을 수행할 때 사용된다. 배열을 변환하거나 새로운 배열을 반환하지 않고, 단순히 각 요소에 대해 주어진 작업만을 수행한다.
const numbers = [1, 2, 3, 4, 5];
let sum = 0;
numbers.forEach((num) => {
sum += num;
});
console.log(sum); // 15
forEach를 통해 numbers 배열의 각 요소를 순회하며 sum 변수에 더해주는 코드이다.
const logCountries = (results) => {
results.forEach((result) => {
console.log(result.country);
});
} ;
위 예시에서는 results 안의 국가명들을 콘솔에 출력하기 위해 forEach를 사용했다. 그러나 forEach는 리턴값이 없기에 렌더링에는 적합하지 않다.
includes는 배열에 특정 값이 포함되어 있는지 여부를 확인하고, 결과로 true 혹은 false를 반환한다.
const fruits = ["apple", "banana", "orange"];
console.log(fruits.includes("banana")); // true
console.log(fruits.includes("kiwi")); // false
fruits 배열에 "banana"가 포함되어 있기에 true를 반환하고, "kiwi"는 포함되어 있지 않기에 false를 반환한다.
그러나 includes를 사용할 때 유의해야할 점이 한 가지 있다. (나 또한 이 문제로 과제 진행과정에서 많이 헤맸었다...🥹)
객체 배열 에서는 includes를 사용할 수 없다.
includes는 엄격한(===) 비교를 통해 배열에 특정 값이 존재하는지 확인한다. 따라서 객체 배열에서 사용하면, 두 객체가 동일한 속성 값을 갖고 있더라도 참조 주소가 다르기에 서로 다른 객체로 간주된다.
(객체는 참조값이기에 배열 내 각 객체들이 서로 다른 메모리 주소를 갖고 있음)
아래의 예시를 살펴보겠다.
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
];
// includes 사용 불가 - 객체를 직접 비교해야 하므로
console.log(users.includes({ name: "Alice", age: 25 })); // false
위 예시에서 { name: "Alice", age: 25 }는 users 배열에 있는 객체와 속성 값은 동일하지만, 다른 메모리 참조를 가지기 때문에 includes는 false를 반환하는 것을 알 수 있다.
따라서 이러한 문제를 해결하기 위해 some을 사용했다.
some은 배열의 요소 중 특정 조건을 만족하는 요소가 있는지 확인하고,true 또는 false를 반환한다. 이 메서드는 배열의 요소 중 하나라도 조건을 만족하면 true를 반환하므로, 조건부 존재 여부를 간단히 검사할 때 유용하게 사용된다.
const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.some((num) => num % 2 === 0);
console.log(hasEven); // true (짝수가 있으므로 true 반환)
위 예시에서 numbers 배열 중 짝수가 하나라도 존재하면 true를 반환한다. some은 조건을 만족하는 첫 번째 요소를 찾으면 더 이상 순회를 하지 않기 때문에 효율적이다.
!!!!!! 또한
some은 엄격한 참조 비교가 아닌 조건을 기반으로 특정 요소가 존재하는지 확인한다. 따라서 이를 통해 객체 배열에서도 특정 속성 값을 기반으로 요소의 존재 여부를 체크할 수 있다.
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
];
// includes 사용 불가 - 객체를 직접 비교해야 하므로
console.log(users.includes({ name: "Alice", age: 25 })); // false
// some 사용 가능 - 조건을 검사
console.log(users.some((user) => user.name === "Alice")); // true
위 예시에서 includes를 사용했을 때는 엄격한 참조 비교로 인해 false가 반환되지만, some을 사용하면 의도했던 값인 true가 반환되는 것을 확인할 수 있다.
const MedalList = ({ results }) => {
const hasGoldWinners = results.some((result) => result.gold > 0);
return (
<div>
{hasGoldWinners ? (
<p>금메달을 딴 국가가 있습니다!</p>
) : (
<p>아직 금메달을 딴 국가가 없습니다.</p>
)}
</div>
);
};
위의 예시에서는 results 배열에서 금메달 수가 0보다 큰 국가가 하나라도 있는지 확인하고, 그에 따라 메시지를 표시한다.
filter는 배열의 요소 중 특정 조건을 만족하는 요소들로만 새로운 배열을 생성할 때 사용되며, 원본 배열은 변경되지 않는다.
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.filter((num) => num % 2 === 0);
console.log(evenNumbers); // [2, 4]
filter를 사용하여 numbers 배열에서 짝수(num % 2 === 0)만을 포함한 새로운 배열 evenNumbers를 생성하는 것을 확인할 수 있다.
const MedalList = ({ results }) => {
const goldWinners = results.filter((result) => result.gold > 0);
return (
<ul>
{goldWinners.map((winner) => (
<li key={winner.id}>{winner.country}: {winner.gold} Gold</li>
))}
</ul>
);
};
위의 예시는 results 배열에서 금메달이 하나라도 있는 국가들만 필터링하여 goldWinners 배열을 생성하고, 이를 <ul> 태그로 렌더링하는 코드이다.
map: 배열의 각 요소에 특정 로직을 적용하여 새로운 배열 생성
forEach: 배열의 각 요소에 대해 특정 작업을 수행하지만, 새로운 배열 생성 X
includes: 배열에 특정 값이 포함되어 있는지 여부를 확인
some: 배열의 요소가 특정 조건을 만족하는지 확인
filter: 배열의 요소 중 특정 조건을 만족하는 요소들로 새로운 배열 생성