본문 바로가기
Script/JavaScript

[JavaScript] Chapter 28. Array forEach

by song.ift 2023. 1. 10.

forEach는 for문과 마찬가지로 반복적인 기능을 수행할 때 사용한다.

하지만 for문처럼 index와 조건식, increase를 정의하지 않아도 callback 함수를 통해 기능을 수행할 수 있다.

 

[].forEach(callback, thisArg)

const arr = [0,1,2,3,4,5,6,7,8,9,10];

arr.forEach(function(element){
  console.log(element); // 0 1 2 3 4 5 6 7 8 9 10
});

// 혹은 arrow 함수 가능
arr.forEach(element => console.log(element));

arr 객체의 요소들이 callback 함수에 순서대로 호출되는 모습을 볼 수 있다.

for문에 비해 좀 더 깔끔하고, 직관적이다. (index가 2씩 증가한다거나 그런 변칙이 없이 arr내 모든 요소들이 callback을 호출하는 것을 알 수 있다.)

 

홀수 배열 만들어보기

forEach는 return이 없다. 즉, callback 함수에 의해서 어떤 결과물을 내놓고 싶으면 함수 밖의 변수를 사용해야한다.

const arr = [0,1,2,3,4,5,6,7,8,9,10];
const oddArray = [];

arr.forEach(function(element){
  if(element%2==1) {
    oddArray.push(element);
  }
});

console.log(oddArray); // [ 1, 3, 5, 7, 9 ]

위와 같은 방법으로 결과물을 만들어낼 수 있지만, 함수 밖 영역의 참조는 예상치 못한 예외 상황을 발생시킬 수 있으므로 scope관리를 잘 해줘야 한다.

사실 이런 경우에는 map 함수를 사용하는 것이 좋다.

 

callback 함수 인자

forEach의 callback 함수에는 배열의 요소 뿐만아니라 index, 전체 배열을 인자로 사용할 수 있다.

const arr = [0,1,2,3,4,5,6,7,8,9,10];

arr.forEach(function(element, index, array){
  console.log(`${array}의 ${index}번째 요소 : ${element}`);
});

/*
0,1,2,3,4,5,6,7,8,9,10의 0번째 요소 : 0
0,1,2,3,4,5,6,7,8,9,10의 1번째 요소 : 1
0,1,2,3,4,5,6,7,8,9,10의 2번째 요소 : 2
0,1,2,3,4,5,6,7,8,9,10의 3번째 요소 : 3
0,1,2,3,4,5,6,7,8,9,10의 4번째 요소 : 4
0,1,2,3,4,5,6,7,8,9,10의 5번째 요소 : 5
0,1,2,3,4,5,6,7,8,9,10의 6번째 요소 : 6
0,1,2,3,4,5,6,7,8,9,10의 7번째 요소 : 7
0,1,2,3,4,5,6,7,8,9,10의 8번째 요소 : 8
0,1,2,3,4,5,6,7,8,9,10의 9번째 요소 : 9
0,1,2,3,4,5,6,7,8,9,10의 10번째 요소 : 10
*/

dom 객체에 onclick을 지정할 때, index를 사용하여 arr의 값을 참조하는 방식으로도 사용할 수 있다.

순수 HTML에서는 dom 객체를 불러오고, onclick을 작성하고, 다시 삽입하는(innerHTML)등의 과정이 복잡하기 때문에 위 방식이 크게 와닿지 않지만,

react에서는 map함수와 index를 사용하여 컴포넌트에 이벤트를 넣는 패턴이 꽤 많다.

 

thisArg

1번의 제목에서 잠깐 언급됐지만, forEach는 callback 함수 이외에 thisArg라는 객체(Object) 인자도 사용할 수 있다.

Mozilla 문서

function Counter() {
  this.sum = 0;
  this.count = 0;
}

Counter.prototype.add = function(array) {
  array.forEach(function(entry) {
    this.sum += entry;
    ++this.count;
  }, this);
  // ^---- 주의
};

var obj = new Counter();
obj.add([2, 5, 9]);
obj.count  // 3
obj.sum  // 16

thisArg의 핵심을 간단하게 풀면 아래와 같다.

const arr = [0,1,2,3,4,5,6,7,8,9,10];
const obj1 = {name: "kim"};
const obj2 = {name: "park"};

arr.forEach(function(element){
  console.log(`${this.name} - ${element}`);
}, obj1);
/*
kim - 0
kim - 1
kim - 2
kim - 3
kim - 4
kim - 5
kim - 6
kim - 7
kim - 8
kim - 9
kim - 10
*/

arr.forEach(function(element){
  console.log(`${this.name} - ${element}`);
}, obj2);
/*
park - 0
park - 1
park - 2
park - 3
park - 4
park - 5
park - 6
park - 7
park - 8
park - 9
park - 10
*/

즉, forEach의 callback에서 this에 대한 참조를 사용할 수 있는데, thisArg가 callback의 this가 되는 것 이다.

forEach(elem => console.log(this.name + elem), obj)에서 this가 elem => console.log(obj.name + elem)와 같아진다는 뜻 이다

근데 이런 문법을 어디다 적용해야 되는건지는 모르겠다.

 

유의할 점

  • for문은 continue나 break로 반복을 제어할 수 있지만, forEach는 throw(예외)를 발생시키지 않으면 중간에 반복을 종료할 수 없다.
  • 만약 조건을 만족할 때 까지만 반복시켜야 한다면 기존 for문이나 every같은 함수를 사용해야 한다.

댓글