JavaScript - 배열 고차 함수 정도는 알아야 배열의 완성

김민재·2021년 8월 5일
0

TIL, Deep Javascript

목록 보기
16/22
post-thumbnail

*🔐Study Keyword :

🔑배열 고차 함수가 무엇인지 알아보고 🗝️어떤 종류가 있는지 살펴보자

- 고차 함수?

  • WHAT IS❓
  • 고차 함수(Higher order function)함수를 인자로 전달받거나 함수를 결과로 반환하는 함수인자로 받은 함수를 필요한 시점에 호출하거나 클로저를 생성하여 반환한다.
  • 이는 함수가 값처럼 인자로 전달하거나 반환할 수 있는 일급 객체이기에 가능하다.
  • 고차 함수는 외부 상태의 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 둔다.

🔅참고🔅) 함수형 프로그래밍?

  • 함수형 프로그래밍이란 순수함수와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거해 복잡성을 해결하고 변수의 사용을 억제해 상태 변경, 부수 효과를 최대한 억제하려는 프로그래밍 패러다임을 말한다.
  • 자바스크립트는 많은 고차 함수를 지원하고 특히 Array 객체, 배열은 매우 유용한 고차 함수를 제공하고 있다.
  • 배열 고차 함수는 활용도가 높으니 사용법을 잘 이해해야한다!

고차 함수의 원본 변경 여부

✏️ 메소드는 this(원본 배열)를 변경한다.
🔒 메소드는 this(원본 배열)를 변경하지 않는다.

‣ 1. Array.prototype.sort : 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 메서드숫자 요소로 구성된 배열 정렬 시

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>
  • sort 메서드객체를 요소로 갖는 배열객체 속성 중 하나의 값을 기준으로 정렬 할 수 있다.
<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>

‣ 2. Array.prototype.forEach : void 🔒

  • 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>
  • forEach 메소드콜백함수를 호출 할 때 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 메소드원본 배열 변경 여부
  • 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 메소드의 두 번째 인수
  • 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 메소드break, continue문을 사용할 수 없다.
  • 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>

3. Array.prototype.map : this🔒

  • 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)한 새로운 배열을 생성하기 위한 고차 함수이다.
  • map 메서드 역시 콜백함수를 호출 할 때 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 메서드두 번째 인수
  • 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>

‣ 4. Array.prototype.filter : this🔒

  • 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 메서드는 자신을 호출한 배열에서 특정 요소를 제거하기 위해 사용할 수 있다.
  • 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>

5. Array.prototype.reduce :this 🔒

  • 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 메서드첫 번째 인수로 콜백 함수, 두 번째 인수로 초기값을 전달받는다.
  • 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>
  • reduce 메서드의 실행과정

  • 첫 순회엔 1>초기값배열의 첫 번째 요소값을 콜백 함수에게 인수로 전달하면서 호출하고 2> 다음 순회에는 콜백 함수의 반환값(초기값 + 첫 번째 요소 값)두 번재 요소값을 또 다시 콜백 함수의 인수로 전달하고 호출하는 과정을 반복하여 최종으로 하나의 결과값을 반환한다.
  • reduce 메서드는 자신을 호출한 배열의 모든 요소를 순회하며 하나의 결과값을 구해야하는 경우에 사용한다.
  • 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>
  • reduce 메서드의 두 번째 인수로 전달하는 초기값은 옵션으로 생략가능하다!
<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>  

‣ 6. Array.prototype.some: this🔒

  • 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>
  • some 메서드첫 번째 인수로 콜백 함수, 두 번째 인수로 this를 전달받는다.
  • forEach, map, filter 메서드 처럼 some 메서드콜백함수(첫 번째 인수)는 4개의 인수 호출한 요소값, 인덱스(currentIndex), this를 순차적으로 전달받을 수 있다.
  • some()도 map(), forEach()와 같이 두번째 인수로 some 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.

‣ 7. Array.prototype.every: 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>
  • every 메서드첫 번째 인수로 콜백 함수, 두 번째 인수로 this를 전달받는다.
  • forEach, map, filter 메서드 처럼 every 메서드콜백함수(첫 번째 인수)는 4개의 인수 호출한 요소값, 인덱스(currentIndex), this를 순차적으로 전달받을 수 있다.
  • some()도 map(), forEach()와 같이 두번째 인수로 some 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.

‣ 8. Array.prototype.find: 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>
  • find 메서드첫 번째 인수로 콜백 함수, 두 번째 인수로 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>

‣ 9. Array.prototype.findIndex: this🔒

-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>
  • findIndex 메서드첫 번째 인수로 콜백 함수, 두 번째 인수로 this를 전달받는다.
  • forEach, map, filter 메서드 처럼 find 메서드콜백함수(첫 번째 인수)는 4개의 인수 호출한 요소값, 인덱스(currentIndex), this를 순차적으로 전달받을 수 있다.
  • filter(), map(), forEach()와 같이 두번째 인수로 find 메서드의 콜백함수 내부에서 사용할 this 객체를 전달할 수 있도 화살표 함수를 사용할 수도 있다.

‣ 10. Array.prototype.flatMap: 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>

*💡conclusion

  • 고차 배열 함수를 잘 활용해야 진정으로 배열을 응용할 수 있다. 고차 배열 함수가 인수로 받는 콜백함수와 this에 대해서도 깊게 공부해보자

#📑Study Source

  1. 책 - 모던 자바스크립트 Deep Dive (529p~551p)
profile
자기 신뢰의 힘을 믿고 실천하는 개발자가 되고자합니다.

0개의 댓글