🔑배열 고차 함수가 무엇인지 알아보고 🗝️어떤 종류가 있는지 살펴보자
- 고차 함수(Higher order function)는 함수를 인자로 전달받거나 함수를 결과로 반환하는 함수로 인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성하여 반환한다.
- 이는 함수가 값처럼 인자로 전달하거나 반환할 수 있는 일급 객체이기에 가능하다.
- 고차 함수는 외부 상태의 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 둔다.
🔅참고🔅) 함수형 프로그래밍?
- 함수형 프로그래밍이란 순수함수와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거해 복잡성을 해결하고 변수의 사용을 억제해 상태 변경, 부수 효과를 최대한 억제하려는 프로그래밍 패러다임을 말한다.
고차 함수의 원본 변경 여부
✏️ 메소드는
this(원본 배열)를 변경한다.
🔒 메소드는this(원본 배열)를 변경하지 않는다.
- sort 메서드는 배열의 요소를 적절하게 정렬해 정렬된 배열을 반환한다.
- sort 메서드는 배열을 일시적으로 문자열로 변환한 후 정렬한다.
<script> const fruits = ['Banana', 'Orange', 'Apple']; fruits.sort(); // ascending(오름차순) console.log(fruits); // [ 'Apple', 'Banana', 'Orange' ] // 원본 직접 변경 fruits.reverse(); // ascending(오름차순)으로 정렬후 descending(내림차순)으로 요소 정렬 console.log(fruits); // [ 'Orange', 'Banana', 'Apple' ] //원본 직접 변경 </script>
숫자 요소로 구성된 배열 정렬 시
sort 메소드의 인자로 정렬 순서를 정의하는 비교 함수를 인수로 전달해야한다.
- 비교 함수는 양수나 음수 또는 0을 반환해야한다.
<script> function compare(a, b) { // 비교함수 if (a < b by some ordering criterion) { return -1; } if (a > b by some ordering criterion) { return 1; } // a===b return 0; } </script>
- 숫자 배열의 오름차순으로 정렬시 비교 함수의 반환값이 0보다 작은 경우, 첫 번째 인수(a)를 우선하여 정렬한다.
- 배열 내림차순으로 정렬시 비교 함수의 반환값이 0보다 큰 경우, 두 번째 인수(b)를 우선하여 정렬한다.
<script> const points = [40, 100, 1, 5, 2, 25, 10]; points.sort((a, b) => return a - b); // 오름차순 정렬 console.log(points); // [ 1, 2, 5, 10, 25, 40, 100 ] console.log(points[0],points[points.length-1]); 1 100, 최대 최솟값 취득 points.sort((a, b) => b - a); // 내림차순 정렬 console.log(points); // [ 100, 40, 25, 10, 5, 2, 1 ] console.log(points[points.length-1], points[0]); 1 100, 최대 최솟값 취득 </script>
객체를 요소로 갖는 배열
은 객체 속성 중 하나의 값을 기준으로 정렬 할 수 있다.<script> const items = [ { name: 'Edward', value: 21 }, { name: 'Sharpe', value: 37 }, { name: 'And', value: 45 }, { name: 'The', value: -12 }, { name: 'Magnetic', value: 13 }, { name: 'Zeros', value: 37 } ]; // case1. 비교함수 정의 후 인수에서 함수 호출하여 전달 function compare(key) { // 비교함수로 매개변수 key는 프로퍼티 key return (a, b) => (a[key] > b[key] ? 1 : (a[key] < b[key] ? -1 : 0)) // 프로퍼티 값이 문자열인 경우 산수 연산(비교시 NaN가 나옴) 대신 비교 연산을 사용한다. } items.sort(compare('value')) // value 기준으로 오름차순 정렬 items.sort(compare('name')) // name 기준으로 오름차순 정렬 // case2. 비교함수를 인수에서 직접 정의 후 함수의 리턴값 전달 items.sort(function (a, b) { return a.value > b.value ? 1 : (a.value < b.value ? -1 : 0); }); console.log(items) // value 기준으로 오름차순 정렬 items.sort(function(a, b) { // name 기준으로 오름차순 정렬 const nameA = a.name.toUpperCase(); const nameB = b.name.toUpperCase(); return nameA > nameB ? 1 : (nameA < nameB ? -1 : 0); }); console.log(items) // name 기준으로 오름차순 정렬 </script>
- forEach 메소드는 for 문을 대체할 수 있는 고차함수로 자신의 내부에서 반복문을 실행한다.
- forEach 메소드는 자신을 호출한 배열의 각 요소를 순회하면서 수행해야할 처리를 인자로 주어진 콜백함수로 전달받아 반복 호출한다.
<script> const numbers = [1, 2, 3]; let pows = []; // for 문으로 순회하는 경우 for (let i = 0; i < numbers.length; i++) { pows.push(numbers[i]**2) } console.log(pows) pows = []; // forEach 메소드를 사용해 순회하는 경우 numbers.forEach(function(item){ // 배열의 모든 요소를 순회하며 인자로 주어진 콜백함수를 실행하여 반복(배열 요소 개수, 3번) 호출한다. return pows.push(item ** 2) }); // arrow 함수로 전달 가능, numbers.forEach(item => pows.push(item ** 2)); console.log(pows) </script>
3개의 인수
를 순차적으로 전달한다.
- forEach 메소드는 인수로 전달한 콜백 함수의 매개변수에 forEach 메서드를 호출한
배열의 요소값
,인덱스
,this
(forEach 메소드를 호출한 배열 자체)를 전달 받을 수 있다.<script> const numbers = [1, 3, 5, 7, 9]; numbers.forEach((item, index, self) => { console.log(`요소값 : ${item}, 인덱스 : ${index}, this: ${JSON.stringify(self)}`); }); </script>
원본 배열 변경 여부
- forEach 메소드는
원본 배열(this)을 변경하지 않지만
콜백 함수를 통해원본 배열(this)을 변경할 수는 있다
.<script> const numbers = [1, 2, 3, 4]; // 원본 배열을 직접 변경하기위해 콜백 함수의 3번째 인자(this)를 사용한다. numbers.forEach((item, index, self)=> { self[index] = Math.pow(item, 2) }); console.log(numbers); // [ 1, 4, 9, 16 ] </script>
두 번째 인수
- forEach 메소드는 1>두번째 인수로 forEach 메서드의 콜백 함수 내부에서 사용할 this로 사용할 객체를 전달할 수 있다.
- 더 나은 방법으로 2>Arrow function, 화살표 함수를 사용하면 this 바인딩을 갖지않는다. 화살표 함수 내부에서 this를 참조하면 상위 스코프인 메서드 내부의 this를 그대로 참조한다.
<script> class Numbers { numberArray = []; // 방법 1 multiply(arr) { // forEach 메서드의 콜백 함수 내부의 this와 multiply 메서드 내부의 this를 일치시켜야한다. arr.forEach(function (item) { this.array.push(item * item); }, this); // forEach 메서드의 콜백 함수 내부에서 this로 사용할 객체를 전달하여 multiply 메서드 내부의 this와 일치시킨다. }; // 방법 2 - Arrow function를 사용하면 this를 생략하여도 동일한 동작을 한다. Square.prototype.multiply = function (arr) { arr.forEach(item => this.array.push(item * item)); }; */ const numbers = new Numbers(); numbers.multiply([1, 2, 3]); console.log(numbers.numberArray); // [ 1, 4, 9 ] </script>
- forEach 메소드는 배열의 모든 요소를 빠짐없이 모두 순회하며 중간에 순회를 중단할 수 없지만 for 문보다 가독성이 좋아 적극 사용을 권장한다.
<script> [1, 2, 3].forEach(item=> { console.log(item)) if (item > 1) break; // SyntaxError: Illegal break statement }); const arr = [1, ,3] // 희소배열 arr.forEach(item=>console.log(item)) // 1, 3 희소배열의 존재하지 않은 요소는 순회에서 제외 </script>
- map 메서드는 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백 함수의 반환값(결과값)들로 구성된 새로운 배열을 생성하여 반환한다.
<script> const numbers = [1, 4, 9]; // 배열의 모든 요소를 순회하며 콜백 함수를 반복 호출한다. const roots = numbers.map(item => Math.sqrt(item)) // 콜백 함수의 반환값들로 구성된 새로운 배열을 만들고 반환값이 없으면 새로운 배열은 비어 있다. // const roots = numbers.map(Math.sqrt), 위 코드의 축약표현 // map 메소드는 새로운 배열을 반환한다 console.log(roots); // [ 1, 2, 3 ] // map 메소드는 원본 배열은 변경x console.log(numbers); // [ 1, 4, 9 ] </script>
- 공통점)
forEach 메소드
와map 메소드
모두 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백함수를 반복 호출한다.- 차이점)
forEach 메소드
- 1> 언제나 undefined를 반환한다.
배열을 순회하며 2>요소 값을 참조하며 단순히 반복문을 대체하기 위한 고차 함수이다.
map 메소드
- 1> 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다.
배열을 순회하며 2>요소 값을 다른 값으로 맵핑(maping)한 새로운 배열을 생성하기 위한 고차 함수이다.
3개의 인수
를 순차적으로 전달한다.
- map 메서드도 forEach 메서드 처럼 콜백 함수의 매개변수를 통해 순차적으로
배열 요소의 값
,요소 인덱스
,this(map 메소드를 호출한 배열)
를 전달 받을 수 있다<script> const numbers = [1, 3, 5, 7, 9]; numbers.map((item, index, self) => { console.log(`요소값 : ${item}, 인덱스 : ${index}, this: ${JSON.stringify(self)}`); }); </script>
두 번째 인수
- map 메서드도 1>두번째 인수로 map 메서드의 콜백함수 내부에서 this로 사용할 객체를 전달할 수 있다.
- 마찬가지로 2>화살표 함수를 사용하면 this 바인딩을 갖지않는다.
<script> class Prefixer { constructor(prefix){ this.prefix = prefix; } // 방법1 add (arr) { return arr.map(function (item) {//item은 배열 요소의 값 return this.prefix + item; }, this); // 외부에서 this를 전달하지 않으면 this는 undefined } // 방법 2 - 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다. add (arr) { return arr.map(item => this.prefix + item)}; } const prefixer = new Prefixer('-webkit-'); console.log(prefixer.add(['-webkit-linear-gradient', '-webkit-border-radius' ])); </script>
- filter 메소드는 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수의 반환값(실행 결과)이 🎇true인 요소로만 구성된 새로운 배열을 반환한다.
<script> const numbers = [1, 2, 3, 4, 5] // filter 메서드 역시 배열의 모든 요소 순회하며 콜백함수 반복 호출 // 콜백 함수의 반환값이 'true'인 요소로만 구성된 새로운 배열을 반환 const odds = numbers.filter(item => item % 2); // 배열에서 홀수인 요소만 필터링한다 (1은 true로 평가된다) console.log(odds); // [ 1, 3, 5 ] </script>
filter 메서드
특징✨1> map 메서드 처럼 콜백 함수의 반환값들로 구성된 새로운 배열을 반환하지만 반환값이 오직 🎇true인 요소로 추출한 새로운 배열을 반환한다.
2> 자신을 호출한 배열에서 필터링 조건을 만족하는 특정 요소만 추출하여 새로운 배열을 만들고 싶을 때 사용한다.
3> filter 메서드가 생성하여 반환한 새로운 배열의 length 프로터티 값은 filter 메서드를 호출한 배열의 length 프로터티 값과 같거나 작다.
-filter 메소드는 콜백함수(첫 번째 인수)를 호출 할 때 3개의 인수
를 순차적으로 전달한다.
forEach와 map 메서드와 처럼 filter 메소드도 콜백 함수의 매개변수를 통해 순차적으로
배열 요소의 값
,요소 인덱스
,this(map 메소드를 호출한 배열)
를 전달 받을 수 있다<script> const numbers = [1, 3, 5, 7, 9]; numbers.filter((item, index, self) => { console.log(`요소값 : ${item}, 인덱스 : ${index}, this: ${JSON.stringify(self)}`); }); </script>
-filter 메소드의 두 번째 인수
- filter 메소드도는 forEach와 map 메서드와 동일하게 1>두번째 인수로 filter 메서드의 콜백함수 내부에서 this로 사용할 객체를 전달 가능하고 2>화살표 함수를 사용하면 this 바인딩을 갖지않는다.
- filter 메서드는 자신을 호출한 배열에서 특정 요소를 제거하기 위해 사용할 수 있다.
- filter 메서드를 사용해 특정 요소를 제거할 경우 중복된 특정 요소를 모두 제거한다.
<script> class Users { constructor(){ this.user = [ {id:1, name:'kim'}, {id:2, name:'minjae'} ]; } // 요소추출 findById(id) { //id가 일치하는 사용자만 반환 return this.user.filter(user => user.id === id); } // 요소제거 remove(id) { //id가 일치하지 않는 사용자를 제거 this.user = this.user.filter(user => user.id !== id); } } const users = new Users(); // id가 1인 사용자만 반환 let user = users.findById(1); console.log(user); //[{id: 1, name: "kim" }] // id가 1인 사용자를 제거 users.remove(1); user = users.findById(1); console.log(user); // [] </script>
- 특정요소 하나만 제거하기 위해선 indexOf 메서드를 통해 특정 요소의 인덱스를 취득한 다음 splice 메서드를 사용해 찾은 인덱스 값을 제거하는 것이 좋다.
<script> const heartArray = ["😂","❤️","❤️","❤️","😍"] console.log(heartArray) // Array(5) [ "😂", "❤️", "❤️", "❤️", "😍" ] heartArray.indexOf("❤️") > -1 ? heartArray.splice(heartArray.indexOf("❤️"), 1) : false console.log(heartArray) // Array(4) [ "😂", "❤️", "❤️", "😍" ] </script>
- reduce 메서드는 배열 순회시 각 요소에 대해 1>이전의 콜백 함수의 반환 값을 2>다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하여 콜백 함수를 실행하고 하나의 결과값을 만들어 반환한다.
<script> const arr = [1, 2, 3, 4, 5]; const sum = arr.reduce(function (accumlator, currentValue, currentIndex, self) { console.log(`${accumlator}+ ${currentValue}=${previousValue +currentValue}); return accumlator + currentValue; }); console.log(sum); // 15 /* 1: 1+2=3 2: 3+3=6 3: 6+4=10 4: 10+5=15 15 */ </script>
첫 번째 인수로 콜백 함수
, 두 번째 인수로 초기값
을 전달받는다.
- reduce 메서드의 콜백함수(첫 번째 인수)에는 4개의 인수
초기값 또는 콜백 함수 이전의 반환 값(accumlator)
,배열의 요소 값(currentValue)
과인덱스(currentIndex)
,this
가 전달된다.<script> const sum = [1, 2, 3, 4].reduce(accumlator, currentValue, currentIndex, self) => accumlator + currentValue, 0); // return 값, 결과는 다음 콜백의 첫번째 인자로 전달된다 console.log(sum); // 10: 1-4까지의 합 </script>
- 첫 순회엔 1>초기값과 배열의 첫 번째 요소값을 콜백 함수에게 인수로 전달하면서 호출하고 2> 다음 순회에는 콜백 함수의 반환값(초기값 + 첫 번째 요소 값)과 두 번재 요소값을 또 다시 콜백 함수의 인수로 전달하고 호출하는 과정을 반복하여 최종으로 하나의 결과값을 반환한다.
- reduce 메서드는 자신을 호출한 배열의 모든 요소를 순회하며 하나의 결과값을 구해야하는 경우에 사용한다.
- reduce 메서드를 활용해
평균 구하기
<script> const values = [1,2,3,4,5,6]; // 마지막 순회면 누적값으로 평균을 구해 반환하고 아니면 누적값을 반환 const avg = values.reduce((acc,cur,i, { length }) => { return i === length - 1 ? (acc + cur) / length : acc + cur; }, 0) console.log(avg) // 3.5 </script>
- reduce 메서드를 활용해
최대값 구하기
<script> const values = [1,2,3,4,5,6]; // 방법1 - 마지막 순회면 누적값으로 평균을 구해 반환하고 아니면 누적값을 반환 const max = values.reduce((acc,cur) => (acc > cur ? acc : cur), 0) // 방법2 - Math.max 메서드를 쓰는게 더 직관적이다. const. max = Math.max(...values); console.log(max) // 6 </script>
- reduce 메서드를 활용해
요소의 중복 횟수 구하기
<script> const alpabets = ['a','b','c','b','a']; const count = alpabets.reduce((acc,cur) => { acc[cur] = (acc[cur] || 0) + 1; return acc; }, {}) /* 1.첫 순회시 acc 초기값 {} cur는 첫 번째 요소인 `a`이다. 2.초기값으로 전달 받은 빈 객체에 요소인 a을 프로퍼티 키로 요소의 개수를 프로퍼티 값으로 할당 3.프로퍼티의 값이 undefined(처음 등자하는 요소)면 프로퍼티 값을 1로 초기화 {a:1}=> {a:1, b:1} => {a:1, b:1, c:1} => {a:1, b:2, c:1} => {a:2, b:2, c:1} */ console.log(count) // {a: 2, b: 2,c: 1} </script>
- reduce 메서드를 활용해
중첩 배열 평탄화
<script> const valuse = [1, [2, 3], 4, [5, 6]]; const flatten = valuse.reduce((acc,cur)=>acc.concat(cur), []); // [1] => [1, 2, 3] => [1, 2, 3, 4] => [1, 2, 3, 4, 5, 6] console.log(flatten) // 중첩 배열 평탄화 시 reduce보다 flat 메서드가 직관적 valuse.flat(); // 평탄화 위한 깊이 인수에 전달 console.log(flat) </script>
- reduce 메서드를 활용해
중복 요소 제거
<script> const valuse = [1, 2, 1, 3, 5, 4, 5, 3, 4, 4]; // 방법 1 - reduce const res = valuse.reduce((acc,cur,i,arr)=> { // 순회 중인 요소의 인덱스가 자신의 인덱스면 처음 순회하는 요소 // 이 요소만 초기값으로 전달 받은 배열에 담아 반환 // 순회 중인 요소가 자신의 인덱스 아니면 중복된 요소 if (arr.indexOf(cur)===i) acc.push(cur); return acc; }, []) console.log(res) // 방법 2 - filter 메서드가 더 직관적 // 순회 중인 요소의 인덱스가 자신의 인덱스라면 처음 순회하는로서 이 요소만 필터링 const res1 = valuse.filter((v,i,arr) => arr.indexOf(v)===i) // [1, 2, 3, 5, 4] // 방법 3 - 중복되지 않는 유일한 값들의 집한인 Set을 사용 // 중복을 허용하지 않는 Set 객체의 특성 활용 중복된 요소 제거 가능 const res2 =[...new Set(valuse)] </script>
초기값은 옵션
으로 생략가능하다!<script>
const sum =[1, 2, 3, 4].reduce((acc, cur)=>acc+cur)
console.log(sum)
</script>
- 하지만 reduce 메서드 호출 시 언제나 초기값을 전달하는 것이 안전하다!
<예시1><script> const sum1 =[].reduce((acc, cur)=>acc+cur) // 타입에러, 빈배열로 초기값이 없어 발생 const sum1 =[].reduce((acc, cur)=>acc+cur, 0) // 0 </script>
- reduce 메서드로 객체의 특정 프로퍼티 값 합산하는 경우 반드시 초기값을 전달해야한다.
<예시2><script> const products = [ {id: 1, price: 100}, {id: 2, price: 200}, {id: 3, price: 300} ]; // 1번째 순회 시 acc는 {id: 1, price: 100}, cur은 {id: 2, price: 200} // 2번째 순회시 acc는 300, cur은 {id: 3, price: 300}으로 // acc에 함수에 객체가 아닌 숫자값이 전달되어 acc.price는 undefined const priceSum = products.reduce((acc, cur) => acc.price + cur.price) console.log(priceSum) // NaN // 1번째 순회 시 acc => 0, cur => {id: 1, price: 100}, cur은 {id: 2, price: 200} // 2번째 순회시 acc => 100, cur => {id: 2, price: 200}으로 // 3번째 순회시 acc => 300, cur => {id: 3, price: 300}으로 const priceSum2 = products.reduce((acc, cur) => acc + cur.price, 0) console.log(priceSum2) // 600 </script>
- some 메서드는 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하는데 이때 콜백 함수의 반환값이
한 번이라도 참이면 true
,모두 거짓이면 false
를 반환한다.- 즉 배열의 '요소 중'에 콜백 함수를 통해 정의한 조건을 만족하는 요소가 '1개 이상' 존재하는지 확인하여 그 결과를 boolean 타입으로 반환한다.
<script> // 배열의 요소 중 10보다 큰 요소가 1개 이상 존재하는지 확인 [5, 10 ,15].some(item => item>10);// ture // 배열의 요소 중 0보다 작은 요소가 1개 이상 존재하는지 확인 [5, 10 ,15].some(item => item < 0);// false // 배열의 요소 중 'a'가 1개 이상 존재하는지 확인 ['a', 'b', 'c'].some(item => item ==='b');// ture // 빈 배열인 경우 언제나 false [].some(item => item > 3);// false </script>
첫 번째 인수로 콜백 함수
, 두 번째 인수로 this를
전달받는다.
- forEach, map, filter 메서드 처럼 some 메서드의 콜백함수(첫 번째 인수)는 4개의 인수
호출한 요소값
,인덱스(currentIndex)
,this
를 순차적으로 전달받을 수 있다.- some()도 map(), forEach()와 같이
두번째 인수
로 some 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.
- every 메서드는 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하는데 이때 콜백 함수의 반환값이
모두 참이면 true
,하나라도 거짓이면 false
를 반환한다.- 즉 배열의 '모든' 요소가 콜백 함수를 통해 정의한 조건을 '모두' 만족하는지를 확인하여 그 결과를 boolean 타입으로 반환한다.
<script> // 배열의 요소 모두 3보다 큰지 확인 [5, 10 ,15].some(item => item>3);// ture // 배열의 요소 모두 10보다 큰지 확인 [5, 10 ,15].some(item => item 10);// false // 빈 배열인 경우 언제나 false [].some(item => item > 3);// false </script>
첫 번째 인수로 콜백 함수
, 두 번째 인수로 this를
전달받는다.
- forEach, map, filter 메서드 처럼 every 메서드의 콜백함수(첫 번째 인수)는 4개의 인수
호출한 요소값
,인덱스(currentIndex)
,this
를 순차적으로 전달받을 수 있다.- some()도 map(), forEach()와 같이 두번째 인수로 some 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.
-ES6에서 도입된 find 메서드는 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하는데 반환값이
true인 첫 번째 요소
를 반환한다.
- 즉 배열의 요소에 대해 콜백 함수를 실행해 그 결과가 참인 '첫번째 요소'를 확인하여 반환하고 참인 요소가 존재하지 않으면 undefined를 반환한다.
<script> const users = [ {id:1, name: 'kim'}, {id:2, name: 'min'}, {id:2, name: 'jae'}, {id:3, name: 'jamie'} ]; // id가 2인 첫 번째 요소를 반환하는데 배열이 아닌 요소를 반환하는 것 users.find(user => user.id ===2) // {id:2, name: 'min'}, </script>
첫 번째 인수로 콜백 함수
, 두 번째 인수로 this를
전달받는다.
- forEach, map, filter 메서드 처럼 find 메서드의 콜백함수(첫 번째 인수)는 4개의 인수
호출한 요소값
,인덱스(currentIndex)
,this
를 순차적으로 전달받을 수 있다.- filter(), map(), forEach()와 같이 두번째 인수로 find 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.
filter
vs find
메서드
filter 메서드
- 콜백 함수의 호출 결과가 true인 요소만 추출한 새로운 배열을 반환하여 반환값은 언제나 ✔ 배열이다.find 메서드
- 콜백 함수의 반환값이 true인 첫 번째 요소를 반환하므로 결과값은 항상 ✔ 해당 요소값이다<script> // filter()는 배열을 반환 [1, 2, 2, 3].filter(item => item === 2);// [2, 2] // find()는 요소를 반환 [1, 2, 2, 3].some(item => item === 2);// 2 </script>
-ES6에서 도입된 findIndex 메서드는 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하는데 반환값이
true인 첫 번째 요소의 인덱스
를 반환한다.
- 즉 배열의 요소에 대해 콜백 함수를 실행해 그 결과가 참인 첫 번째 요소를 확인하여 해당 요소의 인덱스를 반환하고 참인 요소가 존재하지 않으면 -1을 반환한다.
<script> const users = [ {id:1, name: 'kim'}, {id:2, name: 'min'}, {id:2, name: 'jae'}, {id:3, name: 'jamie'} ]; // id가 2인 요소의 인덱스를 구한다 users.findIndex(user => user.id ===2) // 1 users.findIndex(user => user.name ==='jamie') // 3 // 프러퍼티 키와 프로퍼티 값으로 요소의 인덱스를 구하는 경우 다음과 같이 추상화 fuction predicate(key, value){ // key와 value를 기억하는 클로저 반환 return item => item[key]===value; } users.findIndex(predicate('id', 2)) // 1 users.findIndex(predicate('name', 'jamie')) // 3 </script>
첫 번째 인수로 콜백 함수
, 두 번째 인수로 this를
전달받는다.
- forEach, map, filter 메서드 처럼 find 메서드의 콜백함수(첫 번째 인수)는 4개의 인수
호출한 요소값
,인덱스(currentIndex)
,this
를 순차적으로 전달받을 수 있다.- filter(), map(), forEach()와 같이 두번째 인수로 find 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.
- flatMap 메서드는 map 메서드를 통해 새로 생성된 배열을 평탄화한다.
- 즉 배열의 map, flat 메서드를 순차적을 실행하는 효과가=있다.
<script> const arr = ['hello','world'] // map과 flat을 순차적 실행 arr.map(x => x.split('').flat()) // flatMap은 map을 통해 생성된 새로운 배열을 평탄화 arr.flatMap(x => x.split('')) // ['h','e','l','l','o','w','o','r','l','d'] </script>
- 단flatMap 메서드는 flat 메서드 처럼 인수를 전달하여 평탄화 깊이 지정X, 1단계만 평탄화하기에 중첩 배열의 평탄화 깊이를 지정할 경우 map과 flat 메서드를 각각 호출해야한다.
<script> const arr = ['hello','world'] // flatMap은 1단계만 평탄화 arr.flatMap((str, index) => [index, [str, str, length]]) // [0, ['hello', 5], 1, ['world', 5]] // 평탄화 깊이를 지정하기 위해 map과 flat 메서드 각각 호출 arr.map((str, index) => [index, [str, str, length]]).flat(2) // [0, 'hello', 5, 1, 'world', 5] </script>
- 고차 배열 함수를 잘 활용해야 진정으로 배열을 응용할 수 있다. 고차 배열 함수가 인수로 받는 콜백함수와 this에 대해서도 깊게 공부해보자
- 책 - 모던 자바스크립트 Deep Dive (529p~551p)