코딩테스트나 여러 문법에서 forEach 구문을 정말 많이 사용했다. 구차하게 for문을 늘여쓰는 것보다 깔끔하고, i라는 변수를 지정하지 않아도 애초에 함수의 인자로 for문을 돌리는 요소와 idx를 지정할 수 있다. 다음과 같이 말이다.
let val = 5 let arr = [1,2,3,4,5,6] function findTarget(arr,val) { arr.forEach((num,idx) => { if(num == val) { return idx } }) } console.log(findTarget(arr,val))
하지만... 해당 함수는 idx를 반환하지 않는다...undefined로 값이 찍힌다.
일단 우리가 설계한 함수는 for문을 돌면서 찾고자하는 값이 배열에 있는 경우 그 인덱스를 반환하게 한다.
근데 forEach 구문에는 따로 for문의 return이나 while의 break 같은 기능이 없다.
forEach에서 return은 파이썬의 continue와 같이, 다시 for문으로 되돌아가게 만들 뿐이다. 그래서 굳이 쓰자면 try, catch 구문에 감싸서, throw로 에러를 내서 쓸 수는 있는데, 다양한 선택지가 많아서 굳이?
(참고 : https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-forEach%EC%97%90-break%EA%B1%B0%EB%8A%94-%EB%B0%A9%EB%B2%95)
그렇다면 어떤 선택지들이 있는가?
let val = 5 let arr = [1,2,3,4,5,6] function findTarget(arr,val) { for(let i=0; i<arr.length-1; i++) { if(arr[i] == val) { return i } } } console.log(findTarget(arr,val))
for문이 즉시 종료되고 함수값이 return 된다는 것을 기억하자.
근데 선언적으로 굳이 쓰고 싶다..?면 some 함수를 쓸 수 있다.
some은 true가 나올 때까지 실행하고, truthy한 값이 있다면 true를 반환, 배열을 끝까지 돌렸는데 없다면 false를 반환한다. 반환값이 boolean 값이기 때문에, 그냥 for문처럼 return만 찍는다고 능사가 아니다. 외부 변수에 할당을 해주고 return true를 해주어야 한다... 다음과 같이 말이다.
let val = 5 let arr = [1,2,3,4,5,6] function findTarget(arr,val) { let result; arr.some((ele,idx) => { if(ele == val) { result = idx return true } }) return result } console.log(findTarget(arr,val))
무조건 boolean 형태로 반환하기 때문에, 다음과 같이 변수를 할당해주어야 한다.
every는 그 반대다. falsy한 값이 나올 때까지 함수를 실행하고, falsy 하다면 false, 없으면 true를 반환한다. 그래서 true한 1가지 값만 찾는 다음 작업에서는 every가 어울리지 않는다.
let val = 5 let arr = [1,2,3,4,5,6] function findTarget(arr,val) { let result = arr.filter((ele,idx) => ele==val ) return result } console.log(findTarget(arr,val))
그러나 filter 함수는 제한적인 상황에서만 쓸 수 있는데, 배열의 값을 바꾸거나 하지 않고, 조건에 맞는 값만 필터링하기 때문에 보통의 문법으로는 target value에 해당하는 인덱스를 가져올 수 없다. 해당 코드의 결과값은 [5], 배열로 받아오게 된다.
그래서 결국 내가 내린 결론은.... 코드의 가독성이나 추상화정도는 일단 둘째치고 애매하다 싶은 것은 for문을 쓰는 것이 가장 마음이 편하다는 것이다!