👋🏻 JavaScript/📖 자바스크립트 ES6+

[JS] Array 오브젝트의 find, findIndex, fill, includes, flat, flatMap을 알아보자

썸머몽 2023. 6. 21. 20:50
728x90

Array.prototype.find()

배열의 엘리먼트를 하나씩 읽어가며 콜백 함수를 호출한다.

콜백 함수에서 true를 반환하면 종료된다.

 

  • 1번째 파라미터: 콜백 함수 (파라미터: 엘리먼트, 인덱스, 배열 전체)
  • 2번째 파라미터(opt): 콜백 함수에서 this로 참조할 오브젝트
  • 반환: 배열 엘리먼트 OR undefined

 

아래처럼 find는 콜백 함수를 파라미터로 사용하며 해당 콜백 함수는 3가지 파라미터를 사용한다.

const list = ["A", "B", "C"];
const cb = (val, idx, all) => val === "B";
const result = list.find(cb);
console.log(result) // B
const list = ["A", "B", "C"];
const cb = (val, idx, all) => val === 77;
const result = list.find(cb);
console.log(result) // undefined

 

2번째 파라미터인 this로 참조할 오브젝트를 쓰면 아래와 같다.

check 오브젝트가 this로 쓰인다.

 

이 때 콜백 함수 cb2를 일반 함수가 아닌 화살표 함수로 작성할 경우, 2번째 파라미터를 참조할 수 없게 된다. 왜냐하면 화살표 함수는 자체적으로 this를 가지지 않고 주변 영향을 받기 때문에, 화살표 함수일 경우 this는 Window 오브젝트가 되어 일반 함수로 작성해야 한다.

const list = ["A", "B", "C"];

function cb2(val, idx, all) {
    return val === "A" && val === this.check;
};

const result = list.find(cb2, {check: "A"})
console.log(result) // A
const list = ["A", "B", "C"];

const cb2 = (val, idx, all) =>
    val === "A" && val === this.check;
    console.log(this) // Window 오브젝트
;

const result = list.find(cb2, {check: "A"})
console.log(result) // undefined

Array.prototype.findIndex()

배열의 엘리먼트를 하나씩 읽어가며 콜백 함수를 호출한다.

콜백 함수에서 true를 반환하면 종료된다.

 

  • 1번째 파라미터: 콜백 함수 (파라미터: 엘리먼트, 인덱스, 배열 전체)
  • 2번째 파라미터(opt): 콜백 함수에서 this로 참조할 오브젝트
  • 반환: 배열 인덱스 OR -1

 

find 함수와 동일한데, 조건에 부합하는 값이면 값이 아닌 인덱스를 반환한다는 차이만 있다.

값이 없다면 undefined가 아니라 -1을 반환해준다.

const list = ["A", "B", "C"];
const cb = (val, idx, all) => val === "B";
console.log(list.findIndex(cb)) // 1
const list = ["A", "B", "C"];
const cb = (val, idx, all) => val === 77;
console.log(list.findIndex(cb)) // -1

 

indexOf(searchVal, fromIdx)랑 비슷한데, indexOf는 찾고자 하는 값과 검색을 시작할 인덱스를 직접 지정할 수 있는 반면, 콜백 함수가 없어서 특정 다양한 조건으로 체크를 할 수는 없다. (지금처럼 정확히 일치하는 값을 조건으로 한다든지)


Array.prototype.fill()

범위 값을 지정한 값으로 설정하고 반환한다.

 

  • 1번째 파라미터: 설정할 값
  • 2번째 파라미터(opt): 시작 인덱스
  • 3번째 파라미터(opt): 끝 인덱스
  • 반환: 변경된 Array 오브젝트
  • Generic 함수 

 

아래 코드에서는 1번째 파라미터를 "책", 2번째 파라미터를 1로 설정했다.

즉 list의 1번째 인덱스부터 끝까지 책으로 채운다는 뜻이다.

const list = ["A", "B", "C"];
list.fill("책", 1);
console.log(list) // ['A', '책', '책']

 

3번째 파라미터로 끝날 범위를 정해주면 그 범위의 바로 앞까지 채워진다.

그래서 1번째 인덱스부터 3번째 인덱스 바로 앞까지가 책으로 채워졌다.

const list = ["A", "B", "C", "D"];
list.fill("책", 1, 3);
console.log(list) // ['A', '책', '책', 'D']

 

2번째 파라미터와 3번째 파라미터 모두 채우지 않고 채울 값만 정해놓는다면 전체가 대체 대상이 된다.

const list = ["A", "B", "C"];
list.fill("책");
console.log(list) // ['책', '책', '책']

 

Generic 함수면 Array 오브젝트가 아니라 이터러블 오브젝트면 해당 함수를 쓸 수 있다.

like는 Array-like로 오브젝트라서 바로 fill()을 쓸 수 없지만 call()을 통해 like 객체를 호출하고, like 객체를 첫 번째 인자로 전달해서 fill()를 쓸 수 있게 한다.

const like = {0: "A", 1: "B", 2: "C", length: 3};
console.log(Array.prototype.fill.call(like, "책", 1)) 
// {0: 'A', 1: '책', 2: '책', length: 3}

Array.prototype.includes()

대상 배열에 1번째 파라미터 값이 있으면 true / 없으면 false를 반환한다.

 

  • 1번째 파라미터: 비교하려는 값
  • 2번째 파라미터(opt): 비교 시작 인덱스 (디폴트 0)
  • 반환: true / false
  • Generic 함수

 

이건 뭐 알고리즘 풀면서 거의 맨날 썼던 거라 자세한 설명은 생략한다.

const list = [10, 20, 30];

console.log(list.includes(10)); // true
console.log(list.includes(50)) // false
console.log(list.includes(10, 1)) // false

 

제너릭 함수라서 이 경우에도 call로 like 객체를 호출하고 이 이 객체를 1번째 파라미터로 전달한다.

const like = {0: 10, 1: 20, 2: 30, length: 3};
console.log(Array.prototype.includes.call(like, 20)) // true

Array.prototype.flat()

배열 차원을 변환하고 새로운 배열로 설정해 반환한다.

파라미터의 대상 깊이에 따라 변환이 달라진다.

 

  • 1번째 파라미터(opt): 대상의 깊이 (디폴트 1) 
  • 반환: 새로운 배열

 

살짝 설명이 애매해서 MDN을 참고했다.

 

arr1의 1, 2는 1차원 배열이고 3, 4는 2차원 배열이다. 이 때 flat에 파라미터가 없으니 디폴트 값은 1로, 1차원씩 평면이 된다고 보면 된다. 1, 2는 원래 1차원 배열이었고 3, 4는 2차원에서 1차원 평면이 되면서 1차원이 돼 [1, 2, 3, 4]가 출력된다.

const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

 

arr2의 1, 2는 1차원 배열이고 3, 4는 2차원, 5, 6은 3차원 배열이다. 이 때도 파라미터가 없으니 1차원씩 평면이 된다. 3, 4는 위 코드와 동일하게 1차원이 돼 1, 2와 같은 차원이 되지만 5, 6의 경우 3차원에서 2차원이 되기 때문에 아래와 같이 출력된다.

const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

이 때 만약 flat에 파라미터로 2를 줬다면 2차원씩 평면이 돼서 3차원인 5, 6도 1차원으로 출력됐을 것이다.

 

파라미터에 Infinity를 넣으면 어떤 차원이든 1차원으로 출력된다.

const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

파라미터에 0을 넣으면 아무 것도 안 넣은 것(디폴트 1)인 것과 달리 원본을 반환한다.

const list = [1, 2, [3, 4]];
console.log(list.flat(0)) // [1, 2, [3, 4]]

이렇게 평면이 되는 것을 flatted라고 한다. 위 경우는 flatted 되지 않았다.

 

배열에 빈 엘리먼트가 있을 경우에 flat을 하면 빈 부분이 지워지고 디폴트 값인 1이 설정되어 1차원씩 평면이 된다.

const list = [1, 2, , , , [3, 4]];
console.log(list.length) // 6

const change = list.flat();
console.log(change); // [1, 2, 3, 4]
console.log(change.length) // 4

Array.prototype.flatMap()

flat()과 기본 기능은 같다.

배열을 반복하면서 콜백 함수를 호출한다.

 

  • 1번째 파라미터: 콜백 함수(val, idx, all)
  • 2번째 파라미터(opt): 콜백 함수에서 this로 참조할 오브젝트
  • 반환: 새로운 배열(콜백 함수에서 반환한 값을 배열로 반환한다.)

 

그냥 보면 map()이랑 flatMap()이랑 큰 차이가 없어 보인다.

const list = [10, 20];
const cb = (val, idx, all) => {
	return element + 5;
}

console.log(list.flatMap(cb)) // [15, 25]
console.log(list.map(cb)) // [15, 25]

 

그런데 return 하는 값이 지금처럼 엘리먼트 +5가 아니라 1차원 배열이면 차이가 있다.

const list = [10, 20];
const cb = (val, idx, all) => {
	return [val + 5];
}

console.log(list.flatMap(cb)) // [15, 25]
console.log(list.map(cb)) // [[15], [25]]

위 코드처럼 map은 콜백 함수를 통해 반환된 배열을 새로운 배열에 그대로 설정해 2차원 배열로 나오지만, flatMap은 반환하는 과정에서 1차원 줄인 1차원 배열로 반환하여 값이 다르게 출력된다. 

728x90