for, foreach, filter, map, reduce 기능 및 퍼포먼스 차이는?

Yuri Lee·2021년 4월 9일
3

배경

나는 생각 없이 데이터를 가져와 화면에 표출할 때 each 함수를 자주 사용했다. for문은 가독성이 떨어져서 each문으로 간단하게 나타내는 게 보기 좋았기 때문이다. 어김없이 each문을 이용하고 있었는데, 상사분께서 혹시 for, each 등의 성능 차이에 대해 아냐며 검색해 보라는 말씀을 해주셨다.

실제로 반복문은 each 외에도 for, foreach, filter, map, reduce 등 다양한 메서드 혹은 구문을 이용해 구현할 수 있다. 사실 이들의 퍼포먼스 차이에 대해 찾아본 적이 없었다. 데이터를 표출하기 위해서 급급했달까... 😂 생각해보니 반복문을 표현하는 다양한 방법들이 있는데, 이들의 존재 이유는 각 상황마다 사용 사례가 조금씩은 다르지 않을까 싶었다. 그래서 자세히 찾아보기로 결심했다.

compare

for loop

for (int i = 0; i < 10; i++) {
  console.log(arr[i]);
};
  • 가장 빠르고 단순하다. 그래서 효율적이다.
  • 모든 자료형에 대해 사용이 가능하다.
  • 중간에 loop 건너뛰기나 종료가 가능하다. (continue or break)
  • 반복범위 컨트롤이 가능하다. (i++, i–, i+=2*i 등)
  • 변수를 활용할 수 있다. (var i 값을 사용할 수 있다)

forEach

arr.forEach(function(v, i, arr) {
  console.log(v);
});
  • 일반 for문보다 훨씬 가독성이 좋다.
for (var i = 0; i <arr.length; i++) {
  console.log('element', i, arr[i]);
  console.log(arr[i].property1 + arr[i].property2);
  console.log(arr[i].property2);
};

arr.forEach (function (v, i) {
  console.log('element', i, v);
  console.log(v.property1 + v.property2);
  console.log(v.property2);
});
  • 같은 구문이라도 다음과 같이 가독성면에서 차이가 있다.
  • forEach는 복잡한 객체를 처리하는데 있어서 유리하다.
  • 하지만 forEach문은 구문 밖으로 return값을 받지 못한다.
var arr = [1,2,3,4,5];
var newArr = arr.forEach(function(e, i) {
  return e;
});
// undefined
  • 빠른편이다.
  • Array객체에서 사용이 가능하다.
  • 일반 for문보다 가독성이 좋고, 객체형을 다루기가 쉽다.
  • for문과 다르게 중간에 끊을 방법이 없다.
  • return값을 받지 못한다.

filter

var newArr = arr.filter(function(v, i, arr) {
  return condition;
});
  • filter의 가장 큰 특징은 boolean형태의 return값을 갖는다.
  • return값이 true일경우, 그 요소를 반환하고 false일경우, 반환하지 않는다. 기본값은 false이다.
  • 깔끔하게 원하는 요소들만 필터링할 수 있는 유용한 메서드이다.

var arr = [0, , , 1, , , , , 2, , , , 3];
var newArr = arr.filter(function() { return true; });
var newArr = arr.filter(function(el) { return el; });
// 0, 1, 2, 3
  • 빠른편이다.
  • Array객체에서 사용이 가능하다.
  • chainable하다.
  • 빈 배열 요소를 반환하지 않는다.
  • 대용량 배열 처리시 메모리 overflow 가능성이 있다.
  • return값은 true/false이며, 요소를 반환한다.

map

var newArr = arr.map(function(v, i, arr) {
  return condition;
});
  • filter는 return값으로 true/false만 쓸 수 있으며, 요소를 반환하지만, map의 경우 요소가 아닌 새로운 값을 만들어서 return할 수 있다.
var arr = [1, 2, 3, 4, 5];
var newArr = arr.map(function(v, i, arr) {
  return v + 1;
});
// 2, 3, 4, 5, 6
  • 빠른편이다.
  • Array객체에서 사용이 가능하다.
  • chainable하다.
  • 대용량 배열 처리시 메모리 overflow 가능성이 있다.
  • return값 자체를 반환한다.

reduce

var arr = [1, 2, 3, 4, 5];
var newArr = arr.reduce(function(acc, v, i, arr) {
  return acc + v;
});
// 15
  • 첫번째 인자인 accumulator 는 return값을 누적하는데, 계속해서 전달받아서 사용할 수도 있다.
  • accumulator의 초기값을 설정할 수 있다. optional하며 생략시에는 첫번째 return값이 된다.
var arr = [1,2,3,4,5]
var newArr = arr.reduce(function(acc, v, i, arr) {
  return acc + v;
}, 100);
// 115
  • 초기값 설정으로 인해 115 값이 나온 것을 확인할 수 있다.

느낀점

  • 각 메소드마다 조금씩 다른 기능들이 있음을 알게 되었다. 비슷하면서도 다른 그들 🥺🥺
  • (+) each 는 성능이 가장 좋지 않으니 기피하도록 하자...

https://daesuni.github.io/Loop-performance/

profile
Step by step goes a long way ✨

1개의 댓글

comment-user-thumbnail
2022년 7월 29일

깔끔한 정리 감사합니다!

답글 달기