JavaScript

javascript | forEach, map, filter, reduce 메소드, 차이점

sangchu 2022. 7. 26. 01:42

이들은 배열의 각 요소에 대해 수행하는 메소드이다. 

 

 

forEach

forEach는 주어진 함수를 배열 요소 각각에 대해 실행한다.

간단하게 생각하자면 for 반복문을 대신 사용하는 메소드이다.

 

참고한 강의의 강사님은 본인의 뇌피셜로 forEach 함수는

대충 아래 코드의 주석처리 된 부분과 같이 만들어져 있을거라 하셨다.

 

forEach는 두개의 매개변수를 받는데, 첫번째 매개변수는 콜백할 함수(predicate), 두번째는 thisArg를 받는다.

js는 함수형 프로그래밍이 가능하다. 따라서 함수를 매개변수로 넘기는 게 가능하다.

두번째 매개변수인 thisArg는 callback을 실행할 때 this로 사용할 값인데 생략할 수 있다.

/*
function forEach(predicate, thisArg){  
	for(let i = 0; i<a.length; i++{
		predicate(a[i], i) // 호출문
	}
}
*/

let a = [10, 11, 12, 13, 14, 15]
a.forEach(function(v, i){ 
	console.log(v, i); // 콜백, 호출한 predicate의 값 전달받음
});

위 예시는 forEach의 첫번째 매개변수(callback 함수)만 보냈다.

 

callback 함수에서 첫번째 매개변수는 호출한 배열의 원소, 두번째는 인덱스, 세번째는 forEach()를 호출한 배열이 들어간다.

 

아래 예시는 화살표 함수로 써봤다..

각 요소를 받아서 인덱스와 함께 반환해주고 있다. 

 


(해결)

위 코드와 같이 하면 에러가뜬다... 에러 내용을 봐도 이유를 알 수가 없다... 화살표 함수로 하면 되는데 왜 이건 안될까.. 

혹시나 이 글을 보고 있는 사람 중 해결 방법을 알고 있으면 알려주길 바란다.

 

💡 하.. function 오탈자 때문에 그런거였다... 하.. 하하... ㅎ 어쩐지.. 말이 안되더라.. 암튼 function에서도 된다!!


 

 

forEach의 두번째 매개변수도 이용해보자.

앞서 말했듯이 이는 calback 함수를 실행할 때 this로 사용할 값이다.

콜백함수의 세번째 인자로 전달된다.

let a = [10, 11, 12, 13, 14, 15];
a.forEach(function(v,i){
	console.log(v,i,this)
}, [1,2]);

 

 


화살표 함수로 할 시 다른 결과값이 나온다. 이에 대해 찾아봐야겠다.

let a = [10, 11, 12, 13, 14, 15];
a.forEach((v, i) => {
  console.log(v, i, this);
}, [1,2]);


 

 

map

원본 배열 요소 하나하나 탐색하고, 요소들을 이용하여 새로운 배열을 생성해서 리턴해준다.

 

이 또한 대략적인 형태를 코드에 주석으로 써놓았다.

/*
function map(predicate, thisArg){
	let list = [];
	for(let i = 0; i < a.length; i++){
		list.push(predicate(a[i], i));
	}
	return list;
}
*/

let a = [10, 11, 12, 13, 14, 15];
let answer = a.map(function(v, i){
		return v*v;
});
console.log(answer);

 주석을 살펴보면, list라는 새로운 빈 배열을 생성해

for문을 돌며 콜백으로 얻은 값을 배열에 넣는다(push).

 

아래 결과를 보면 각 요소를 곱한 값을 받은 결과를 확인할 수 있다.

 

map 함수는 새로운 배열도 원본 배열과 길이가 무조건 같다.

아래 예시를 보자.

let a = [10, 11, 12, 13, 14, 15];
let answer = a.map(function(v, i){
		if(v%2==0) return v;
});
console.log(answer);

조건문을 통해 짝수 값만 넘겨주었다. 

조건에 일치하지 않은 값(홀수)은 undefined로 넘겨준 것이다!

 

 

filter

새로운 배열을 생성해서 리턴한다.

map과 달리 원본 배열의 길이와 다를 수 있다.

참인 요소만 리턴하기 때문이다.

즉, 원본 배열에서 특정 원하는 값만 뽑아내서 새로운 배열을 생성하고 싶을때 사용한다.

 

이 또한 대략적인 형태를 코드에 주석으로 써놓았다.

/*
function filter(predicate, thisArg){
	let list = [];
	for(let i = 0; i < a.length; i++){
		if(predicate(a[i], i)){  // 참일때만 push
			list.push(a[i]);
		}	
	}
	return list;
}
*/

let a = [10, 11, 12, 13, 14, 15];
let answer = a.filter(function(v, i){
		return v%2==0
});
console.log(answer);

이는 짝수만 추출해주는 코드이다.

return에서 짝수일 때만 참이게 했기 때문이다.

 

 

reduce

이는 위의 배열을 반환하는 메소드와 달리, 하나의 결과값을 반환한다.

또한 콜백할 함수의 매개변수의 역할도 다르다.

첫번째 매개변수는 누적할 값, 두번째는 값이 들어간다.

또한 reduce의 두번째 매개변수는 초깃값이 들어간다.

 

이렇게만 말하면 이해가 안될 수 있으니 아래 코드를 보자

이 또한 대략적인 형태를 코드에 주석으로 써놓았다.

/*
function reduce(predicate, val){
	let result = val;
	for(let i = 0; i < a.length; i++){
			result = predicate(result, a[i]);	
	}
	return result;
}
*/

let a = [10, 11, 12, 13, 14, 15];
let answer = a.reduce(function(acc, v){ // acc: 누적, v: value
		return acc + v;
}, 0); // 두번째 인자는 초깃값, 즉 acc= 0
console.log(answer);

이는 배열의 각 요소를 누적해서 더하는 코드이다.

실제로 이 메소드는 알고리즘에서는 원본배열 합을 구할 때 주로 쓰인다고 한다.

 

조건문을 잘 걸면 최솟값 구하는 알고리즘으로 쓰일 수 있지만, 굳이 이렇게 할 필요없고 Math 외장모듈을 이용하면 된다.(그냥 이렇게도 쓰일 수 있다)

 

 

 

참고: Mdn, inflearn js 알고리즘 강좌