home강의 홈으로
Section 7. 배열
Lesson 3. 고차함수 메서드들

👉 MDN 문서 보기


배열의 고차함수 higher order function 메서드

  • 다른 함수(콜백 함수 callback function)를 인자로 받음
  • 함수형 프로그래밍 - 변수 사용 없이 순회 작업들을 코딩

1. forEach - 각 요소를 인자로 콜백함수 실행

  • 💡 for문의 좋은 대체제
  • ⚠️ 단점 : 예외를 던지지 않으면 종료할 수 없음 - break, continue 사용 불가

인자들:

  • 콜백함수 - 인자: ( 현재 값, 현재 값의 인덱스, 해당 배열 )
  • thisArg - this 주제 섹션에서 다룰 것
const arr = [1, 2, 3, 4, 5]; const result = arr.forEach(itm => { console.log(itm); }); // 💡 결과로는 undefined 반환 - 실행 자체를 위한 메서드 console.log('반환값:', result);


const arr = [1, 2, 3, 4, 5]; // 현존하는 함수를 인자로 - 💡 결과 살펴볼 것 arr.forEach(console.log);


const arr = [10, 20, 30, 40, 50]; // 콜백함수의 인자가 둘일 때 arr.forEach((itm, idx) => { console.log(itm, idx); }); const logWithIndex = (itm, idx) => { console.log(`[${idx}]: ${itm}`); } arr.forEach(logWithIndex);


const arr = [1, 2, 3, 4, 5]; // 콜백함수의 인자가 셋일 때 arr.forEach((itm, idx, arr) => { // 💡 세 번째 인자는 원본 배열의 참조임 arr[idx]++; console.log(itm); }); // 이런 식으로 원본을 수정해버릴 수 있음 console.log(arr);

2. map - 각 요소를 주어진 콜백함수로 처리한 새 배열 반환

img

인자들:

  • 콜백함수 - 인자: ( 현재 값, 현재 값의 인덱스, 해당 배열 )
  • thisArg
const orgArr = [1, 2, 3, 4, 5]; // ⭐️ 각 콜백함수는 어떤 값을 반환해야 함 const arr1 = orgArr.map(i => i + 1); const arr2 = orgArr.map(i => i * i); const arr3 = orgArr.map(i => i % 2 ? '홀수' : '짝수'); console.log(arr1); console.log(arr2); console.log(arr3);


const orgArr = [ { name: '사과', cat: '과일', price: 3000 }, { name: '오이', cat: '채소', price: 1500 }, { name: '당근', cat: '채소', price: 2000 }, { name: '살구', cat: '과일', price: 2500 }, { name: '피망', cat: '채소', price: 2500 }, { name: '딸기', cat: '과일', price: 5000 } ]; const arr1 = orgArr.map(itm => { // 💡 블록 안에서는 return 문 필요함 return { name: itm.name, cat: itm.cat } }); console.log(arr1); // 디스트럭쳐링 사용 (편의에 따라 적절히) const arr2 = orgArr.map(({name, cat}) => { return { name, cat } }); console.log(arr2); const joined = orgArr .map(({name, cat, price}, idx) => { return `${idx + 1}: [${cat[0]}] ${name}: ${price}원` }) .join('\n - - - - - - - - - \n'); console.log(joined);

3. find, findLast, findIndex, findLastIndex - 주어진 기준으로 검색

콜백함수로에 인자로 넣었을 때 true를 반환하는

  • find - 첫 번째 값 반환
  • findLast - 마지막 값 반환
  • findIndex - 첫 번째 값의 인덱스 반환
  • findLastIndex - 마지막 값의 반환

공통 인자들:

  • 콜백함수 - 인자: ( 현재 값, 현재 값의 인덱스, 해당 배열 )
  • thisArg
const arr = [1, 2, '삼', 4, 5, 6, '칠', 8, 9]; const isString = i => typeof i === 'string'; const isBoolean = i => typeof i === 'boolean'; console.log( arr.find(isString), arr.findLast(isString), arr.findIndex(isString), arr.findLastIndex(isString) ); // 없을 시 값은 undefined, 인덱스는 -1 반환 console.log( arr.find(isBoolean), arr.findLast(isBoolean), arr.findIndex(isBoolean), arr.findLastIndex(isBoolean) );


const arr = [ { name: '사과', cat: '과일', price: 3000 }, { name: '오이', cat: '채소', price: 1500 }, { name: '당근', cat: '채소', price: 2000 }, { name: '살구', cat: '과일', price: 2500 }, { name: '피망', cat: '채소', price: 3500 }, { name: '딸기', cat: '과일', price: 5000 } ]; const isCheapFruit = i => { return i.cat === '과일' && i.price < 3000; } console.log( arr.find(({cat}) => cat === '채소').name, arr.findLast(isCheapFruit).name );

4. some, every - 어떤/모든 요소가 기준을 충족하는지 확인

콜백함수에 인자로 넣은

  • some - 요소들 중 하나라도 true를 반환하는가 여부 반환
  • every - 모든 요소가 true를 반환하는가 여부 반환

인자들:

  • 콜백함수 - 인자: ( 현재 값, 현재 값의 인덱스, 해당 배열 )
  • thisArg
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log( arr.some(i => i % 2), arr.every(i => i % 2), arr.some(i => i < 0), arr.every(i => i < 10) ); const arr = [ { name: '사과', cat: '과일', price: 3000 }, { name: '오이', cat: '채소', price: 1500 }, { name: '당근', cat: '채소', price: 2000 }, { name: '살구', cat: '과일', price: 2500 }, { name: '피망', cat: '채소', price: 3500 }, { name: '딸기', cat: '과일', price: 5000 } ]; const isCheapVege = i => { return i.cat === '채소' && i.price < 2000; } const isPlant = ({cat}) => { return ['과일', '채소'].includes(cat); } console.log( arr.some(isCheapVege), arr.every(isCheapVege), arr.some(isPlant), arr.every(isPlant) );

5. filter - 주어진 기준을 충족하는 요소들로 새 배열 만들어 반환

img

  • ⭐️ 원본 배열을 수정하지 않음

인자들:

  • 콜백함수 - 인자: ( 현재 값, 현재 값의 인덱스, 해당 배열 )
  • thisArg
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const odds = arr.filter(i => i % 2); const evens = arr.filter(i => !(i % 2)); const largerThan3 = arr.filter(i => i > 3); console.log(odds); console.log(evens); console.log(largerThan3); const arr = [ { name: '사과', cat: '과일', price: 3000 }, { name: '오이', cat: '채소', price: 1500 }, { name: '당근', cat: '채소', price: 2000 }, { name: '살구', cat: '과일', price: 2500 }, { name: '피망', cat: '채소', price: 3500 }, { name: '딸기', cat: '과일', price: 5000 } ]; console.log( '과일 목록:', arr .filter(({cat}) => cat === '과일') .map(({name}) => name) .join(', ') );

6. reduce, reduceRight

  • 주어진 콜백함수에 따라 값들을 접어 나감

img

인자들:

  • 콜백함수 - 인자: ( 이전값, 현재값, 현재 인덱스, 해당 배열 )
  • 초기화 값

💡 초기화 값이 없을 때는 첫 번째와 두 번째 값부터

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log( arr.reduce((prev, curr, idx) => { console.log(`p: ${prev}, c: ${curr}, i: ${idx}`); return prev + curr; }) );

초기화 값이 있을 때

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log( arr.reduce((prev, curr, idx) => { console.log(`p: ${prev}, c: ${curr}, i: ${idx}`); return prev + curr; }, 10) );
  • 인덱스가 0부터 시작함 주목

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 곱해나가기 console.log( arr.reduce((prev, curr, idx) => { console.log(`p: ${prev}, c: ${curr}, i: ${idx}`); return prev * curr; }) ); const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 더하기와 빼기 반복 console.log( arr.reduce((prev, curr, idx) => { console.log(`p: ${prev}, c: ${curr}, i: ${idx}`); return idx % 2 ? prev + curr : prev - curr; }) ); const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 홀수와 짝수 갯수 console.log( arr.reduce((prev, curr) => { return { odd: prev.odd + curr % 2, even: prev.even + (1 - (curr % 2)), } }, { odd: 0, even: 0 }) );

reduce vs reduceRight

const arr = ['가', '나', '다', '라', '마', '바', '사']; console.log( arr.reduce((prev, curr, idx) => { console.log(`p: ${prev}, c: ${curr}, i: ${idx}`); return prev + curr; }) ); console.log( arr.reduceRight((prev, curr, idx) => { console.log(`p: ${prev}, c: ${curr}, i: ${idx}`); return prev + curr; }) );
  • reduceRight은 인덱스도 거꾸로 진행됨에 주목

const arr = [ { name: '사과', cat: '과일', price: 3000 }, { name: '오이', cat: '채소', price: 1500 }, { name: '당근', cat: '채소', price: 2000 }, { name: '살구', cat: '과일', price: 2500 }, { name: '피망', cat: '채소', price: 3500 }, { name: '딸기', cat: '과일', price: 5000 } ]; ['과일', '채소'].forEach(category => { console.log( `${category}의 가격의 합:`, arr .filter(({cat}) => cat === category) .map(({price}) => price) .reduce((prev, curr) => prev + curr) ); });

⭐️ 만약 위 기능을 배열 메서드와 체이닝 없이 짰다면?

  • 중간 과정을 저장하기 위한 변수 또는 내용이 바뀌는 참조형 데이터들이 사용되었을 것
  • 함수형 프로그래밍 - 변수들을 코드에서 감추어 부수효과로 인한 문제 방지


7. sort - 배열을 ( 주어진 기준대로 ) 정렬

  • ⚠️ 배열 자체의 순서를 바꿈 - 원본 수정
  • ➕ 해당 배열을 반환

인자들:

  • 콜백함수(필수 아님) - 인자: ( 앞의 값, 뒤의 값 )

1. 인자가 없을 시

const arr = ['라', '사', '다', '가', '바', '마', '나']; arr.sort(); console.log(arr); let randomWord = 'DBKGICAHFEJ'; console.log( randomWord .split('') .sort() // .reverse() .join('') ); console.log(randomWord);


// ⚠️ 숫자일 시 문제가 생김 const arr = [1, 2, 30, 400, 10, 100, 1000]; console.log(arr.sort());
  • 숫자를 문자열로 암묵적 변환하여 오름차순 정렬

⭐️ 정확한 정렬을 위해 - 콜백 함수 사용

  • 두 인자 ab : 인접한 두 요소
  • 0보다 큰 값 반환 : b를 앞으로 - 순서 뒤집음
  • 0 반환: 순서 유지 - ECMAScript 표준은 아니므로 환경마다 다를 수 있음
  • 0보다 작은 값 반환 : a를 앞으로 - 사실상 순서 유지

브라우저마다 동작 디테일 다름

인접한 앞의 것과 뒤의 것을, 콜백함수의 첫 번째와 두 번째 인자 (a, b)
어떤 것으로 받아오는지가 브라우저마다 다릅니다.

이 부분 때문에 아래의 실습 중 혼동이 올 수 있는데
끝까지 진행해보시면 큰 어려움 없이 이해하실 수 있을 것입니다.



👇 브라우저마다 로그 내역이 다름 주목 크롬계열 vs 파이어폭스 등...

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 변함없음 console.log( arr.sort((a, b) => { console.log(`a: ${a}, b: ${b}`); return 1; }) ); const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 순서 거꾸로 console.log( arr.sort((a, b) => { console.log(`a: ${a}, b: ${b}`); return -1; }) ); const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; // 셔플 - ⚠️ 위의 코드들과 로그 갯수 비교 console.log( arr.sort((a, b) => { console.log(`a: ${a}, b: ${b}`); return Math.random() - 0.5; }) );


아래의 실습결과는 환경이 달라도 같음

  • ab의 의미에 따라 반환값 양수/음수의 음수의 의미도 바뀌기 때문
  • 따라서 실무에서는 실행환경을 신경쓸 필요 없음

const arr = [1, 2, 30, 400, 10, 100, 1000]; console.log( arr.sort((a, b) => a - b) ); console.log( arr.sort((a, b) => b - a) );

⚠️ 숫자가 아닐 경우 직접 반환값을 명시

// NaN을 반환하므로 콜백에 사용 불가 console.log('A' - 'B');


const arr = ['F', 'E', 'I', 'A', 'H', 'C', 'D', 'J', 'G', 'B']; console.log( arr.sort((a, b) => a > b ? 1 : -1) ); console.log( arr.sort((a, b) => a < b ? 1 : -1) );

💡 둘 이상의 기준 사용

const arr = [ { name: '사과', cat: '과일', price: 3000 }, { name: '오이', cat: '채소', price: 1500 }, { name: '당근', cat: '채소', price: 2000 }, { name: '살구', cat: '과일', price: 2500 }, { name: '피망', cat: '채소', price: 3500 }, { name: '딸기', cat: '과일', price: 5000 } ]; console.log( arr .sort((a, b) => { if (a.cat !== b.cat) { return a.cat > b.cat ? 1 : -1; } return a.price > b.price ? 1 : -1; }) .map(({name, cat, price}, idx) => { return `${idx + 1}: [${cat[0]}] ${name}: ${price}원` }) .join('\n - - - - - - - - - \n') );

7. flatMap - map 한 다음 flat 매핑해서 펼침

인자들:

  • 콜백함수 - 인자: ( 현재 값, 현재 값의 인덱스, 해당 배열 )
  • thisArg
const arr = [1, 2, 3, 4, 5]; console.log( arr.flatMap(i => i) ); console.log( arr.flatMap(i => [i, i, i]) ); console.log( arr.flatMap(i => [i * 10, i * 100, i * 1000]) );


const arr = [1, 2, 3, 4, 5]; // 💡 한 단계만 펼침 console.log( arr.flatMap(i => [i, [i], [[i]]]) ) const word = '하나 둘 셋 넷 다섯 여섯 일곱 여덟 아홉 열'; console.log( word .split(' ') .flatMap(i => i.split('')) );

🤔얄코에게 질문하기질문은 반.드.시 이리로 보내주세요! ( 강의사이트 질문기능 ✖ )

강의에서 이해가 안 되거나 실습상 문제가 있는 부분,
설명이 잘못되었거나 미흡한 부분을 메일로 알려주세요!

답변드린 뒤 필요할 경우 본 페이지에
관련 내용을 추가/수정하도록 하겠습니다.

이메일 주소
yalco@yalco.kr
메일 제목 (반드시 아래 제목을 붙여넣어주세요!)
[질문] 제대로 파는 자바스크립트 (무료 파트) 7-3

🛑질문 전 필독!!

  • 구글링을 먼저 해 주세요. 들어오는 질문의 절반 이상은 구글에 검색해 보면 1분 이내로 답을 찾을 수 있는 내용들입니다.
  • 오류 메시지가 있을 경우 이를 구글에 복붙해서 검색해보면 대부분 짧은 시간 내 해결방법을 찾을 수 있습니다.
  • 강의 페이지에 추가사항 등 놓친 부분이 없는지 확인해주세요. 자주 들어오는 질문은 페이지에 추가사항으로 업데이트됩니다.
  • "유료파트의 강의페이지는 어디 있나요?" - 각 영상의 시작부분 검은 화면마다 해당 챕터의 강의페이지 링크가 있습니다.
  • 질문을 보내주실 때는 문제가 어떻게 발생했고 어떤 상황인지 등을 구체적으로 적어주세요. 스크린샷을 첨부해주시면 더욱 좋습니다.
🌏 Why not change the world?