Array의 내장 메소드를 이용해서 주어진 문제를 풀어보자.
...였으나 문제가 4개뿐인데다가 너무 쉬워서 차라리 Array의 메소드를 한 번씩 살펴보기로 했다. 원래 배열을 mutate하는 경우 🛑으로 표시하였다.
배열은 대괄호를 이용한 리터럴 표기법으로 생성할 수도 있고, Array() 생성자를 이용해 생성할 수도 있다. 생성자에 숫자 하나가 인자로 전달되면 배열의 길이로 해석하고, 그 외에는 인자들로 구성된 배열을 생성한다.
유사 배열 객체나 반복 가능한 객체로부터 배열을 생성한다. mapping function을 지정할 수도 있다.
Array.from("foo"); // ['f', 'o', 'o']
Array.from([1, 2, 3], (x) => 2 * x); // [2, 4, 6]
인자가 Array이면 true, 아니면 false를 반환한다.
인자들로 구성된 배열을 생성하며, 숫자 하나를 전달해도 생성자와 달리 그 숫자로 구성된 배열을 생성한다.
Array(5); // [ , , , , ]
Array.of(5); // [5]
주어진 위치의 요소를 반환한다. index로 음수도 올 수 있고, 이 경우 끝에서부터 위치를 계산한다. index가 배열에 없는 경우 undefined를 반환하기 때문에 index가 배열 길이를 초과하는 경우에도 undefined를 반환한다.
const array = [5, 12, 8, 130, 44];
array.at(3); // 130
array.at(-5); // 5
array.at(5); // undefined
배열의 끝에 주어진 값을 합친 새 배열을 반환한다. value는 개수와 타입에 관계없이 전달할 수 있다. 단, 객체를 전달할 경우 참조를 복사한다.
const array1 = [1, 2, 3];
const array2 = [7, 8, 9];
array1.concat(4, [5, 6], array2, "Nice!");
// 결과: [1, 2, 3, 4, 5, 6, 7, 8, 9, "Nice!"]
start부터 end 전까지를 복사하여 target 위치에 붙여넣는다. start와 end는 각각 0과 length를 기본값으로 갖는다. Array 안에서 데이터를 이동할 때 유용하다고 한다. 아래는 MDN에 소개된 예제이다.
[1, 2, 3, 4, 5].copyWithin(-2);
// [1, 2, 3, 1, 2]
[1, 2, 3, 4, 5].copyWithin(0, 3);
// [4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4);
// [4, 2, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(-2, -3, -1);
// [1, 2, 3, 3, 4]
배열의 index와 값을 이용한 iterator를 반환한다. 빈 슬롯은 undefined로 취급한다.
const array = ['a', 'b', 'c'];
array.entries() // [0, 'a'], [1, 'b'], [2, 'c']로 구성된 iterator
for (const [index, value] of array.entries()) {
console.log(`${value} at ${index}`);
}
// a at 0
// b at 1
// c at 2
배열의 모든 요소가 callback 함수를 통과하는지 검사한다. 정확하게는 callback이 false를 반환할 때까지 배열을 순회한다. callback 함수는 element, index, array를 인수로 받는다. 빈 슬롯은 건너뛴다.
const isPositive = (value) => value > 0;
[1, 2, 3].every(isPositive); // true
[0, 5].every(isPositive); // false
[].every(isPositive); // true
start부터 end 전까지의 모든 요소를 value로 대체한다. 객체는 참조를 복사한다.
[1, 2, 3].fill(0); // [0, 0, 0]
[1, 2, 3].fill(0, 1); // [1, 0, 0]
[1, 2, 3].fill(0, 0, -1); // [0, 0, 3]
const array = Array(3).fill({}) // [{}, {}, {}]
array[0].value = "hi";
// [{value: "hi"}, {value: "hi"}, {value: "hi"}]
callback 함수를 통과하는 요소로 구성된 새로운 배열을 반환한다.
const array = [3, 61, 210, -41, 10, 0, -117];
array.filter((element) => element > 0); // [3, 61, 210, 10]
array.filter((element) => element === 1); // []
callback 함수를 통과하는 첫 요소의 값을 반환하며, 찾을 수 없으면 undefined를 반환한다.
const array = [3, 1, -5, 4];
array.find((element) => element < 0); // -5
array.find((element) => element > 10); // undefined
callback 함수를 통과하는 첫 요소의 인덱스를 반환하며, 찾을 수 없으면 -1을 반환한다.
const array = [3, 1, -5, 4];
array.findIndex((element) => element < 0); // 2
array.findIndex((element) => element > 10); // -1
callback 함수를 통과하는 마지막 요소의 값을 반환하며, 찾을 수 없으면 undefined를 반환한다.
callback 함수를 통과하는 마지막 요소의 인덱스를 반환하며, 찾을 수 없으면 -1을 반환한다.
중첩 배열을 depth만큼 평탄화한다. 빈 슬롯도 제거한다.
[1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]].flat();
// [1, 2, [3, 4, [5, 6, [7, 8, 9, 10]]]]
[1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]].flat(2);
// [1, 2, [3, 4, [5, 6, 7, 8, 9, 10]]]
[1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]].flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
배열을 순회하며 callback을 수행한 결과를 담은 배열을 깊이 1로 평탄화한다.
const sentences = ["All human beings", "are born free and equal"];
sentences.map((sentence) => sentence.split(" "));
// [["All", "human", "beings"], ["are", "born", "free", "and", "equal"]]
sentences.flatMap((sentence) => sentence.split(" "));
// ["All", "human", "beings", "are", "born", "free", "and", "equal"]
배열을 순회하며 callback을 수행한다. map과는 다르게 반환값은 없다.
["Hello", "I'm", "an", "array"].forEach((element) => console.log(element));
// Hello
// I'm
// an
// array
배열이 value를 포함하고 있는지 판별한다. start를 지정하면 해당 index부터 검사를 시작한다.
[1, 2, 3].includes(1); // true
[1, 2, 3].includes("1"); // false
[1, 2, 3].includes(1, 1); // false
start부터 값이 value인 첫 요소를 찾아 index를 반환하고, 없다면 -1을 반환한다.
const array = [3, 1, 4, 1, 5];
array.indexOf(1); // 1
array.indexOf(1, 1); // 3
array.indexOf(0); // -1
배열의 모든 요소를 seperator로 구분하여 하나의 문자열로 만든다. 기본값은 쉼표(,)이다.
const array = ['a', 'b', 'c'];
array.join(); // "a,b,c"
array.join(" "); // "a b c"
배열의 각 인덱스를 키로 가지는 iterator를 반환한다.
for (const key of ['a', 'b', 'c'].keys()) {
console.log(key);
}
// 0
// 1
// 2
start부터 값이 value인 첫 요소를 역순으로 찾아 index를 반환하고, 없다면 -1을 반환한다.
배열을 순회하며 callback을 호출하여 반환된 결과로 이루어진 배열을 반환한다.
[1, 2, 3].map((element) => element ** 2); // [1, 4, 9]
배열의 마지막 요소를 제거하고 그 요소를 반환한다.
const array = [1, 2, 3, 4];
array.pop(); // 4
console.log(array); // [1, 2, 3]
배열의 끝에 value를 추가하고 새로운 배열의 길이를 반환한다. value를 여러 개 전달할 수도 있다.
const array = [1, 2, 3, 4];
array.push(5); // 5
console.log(array); // [1, 2, 3, 4, 5]
배열을 순회하며 callback 함수를 누적하여 실행한 결화를 반환한다. reduce의 callback 함수는 map이나 forEach와는 다르게 accumulator, currentValue, currentIndex, array를 인자로 받는다. 지금 callback 함수의 반환값이 다음 callback 함수 호출시의 accumulator로 전달된다.
[1, 2, 3, 4].reduce((acc, cur) => acc + cur, 0); // 10
reduce와 같지만 순회 방향이 반대이다.
['a', 'b', 'c'].reduce((acc, cur) => acc + cur); // "abc"
['a', 'b', 'c'].reduceRight((acc, cur) => acc + cur); // "cba"
배열을 반대로 뒤집은 후 참조를 반환한다.
const array = [1, 2, 3];
const array2 = array.reverse(); // [3, 2, 1]
console.log(array); // [3, 2, 1]
배열의 첫 요소를 제거하고 그 요소를 반환한다.
const array = [1, 2, 3];
const first = array.shift(); // 1
const last = array.pop(); // 3
console.log(array); // [2]
start부터 end 전까지를 복사해서 반환한다.
const array = [1, 2, 3, 4];
const sliced = array.slice(1, 3); // [2, 3]
console.log(array); // [1, 2, 3, 4]
배열 안의 어떤 요소라도 callback 함수를 통과하면 true를, 아니라면 false를 반환한다.
const isPositive = (value) => value > 0;
[1, 2, 3].some(isPositive); // true
[0, 5].some(isPositive); // true
[].some(isPositive); // false
배열을 callback 함수에 따라 정렬하고 그 배열을 반환한다. callback은 두 개의 요소 a, b를 인자로 받아서 음수, 0, 또는 양수를 반환한다. 음수면 a, b 순서, 양수면 b, a 순서로 정렬한다. number를 정렬할 때 callback을 전달하지 않으면 문자열로 변환하여 비교하기 때문에 오류가 발생할 수 있다.
const array = [1, 10, 8, 3];
array.sort(); // [1, 10, 3, 8]
array.sort((a, b) => a - b); // [1, 3, 8, 10]
배열에서 값을 제거하거나 추가하고 제거된 요소를 담은 배열을 반환한다. start는 변경할 위치, count는 제거할 요소의 수, item은 추가할 요소들이다. count를 지정하지 않으면 start 이후를 모두 제거하고, item을 지정하지 않으면 추가하지 않고 제거만 한다. count로 0을 전달하면 제거하지 않고 추가만 한다.
const fruits = ['🍇', '🍉', '🍎', '🍎', '🍓'];
fruits.splice(2, 1, '🍌');
// ['🍇', '🍉', '🍌', '🍎', '🍓']
fruits.splice(3);
// ['🍇', '🍉', '🍌']
fruits.splice(1, 0, '🍎', '🍓', '🍈');
// ['🍇', '🍎', '🍓', '🍈', '🍉', '🍌']
배열을 locales에 맞는 문자열로 변환하여 반환한다. 각 요소에 대해 toLocaleString()을 실행한 결과를 seperator로 분리하여 변환한다.
const number = 10_000;
const date = new Date();
const array = [number, date];
array.toLocaleString(); // "10,000,20XX. X. X. 오전 X:XX:XX"
array.toLocaleString("en-US"); // "10,000,8/1/2023, 2:47:58 PM"
reverse()와 같은 역할을 하는 복사 메소드다.
sort()와 같은 역할을 하는 복사 메소드다.
splice()와 같은 역할을 하는 복사 메소드다.
join을 호출하여 배열의 요소를 쉼표(,)로 연결한 문자열을 반환한다. 배열을 문자열로 취급할 때 이 메소드가 자동으로 호출된다.
const array = ['a', 'b', 'c'];
array.toString(); // "a,b,c"
array + 'd'; // "a,b,cd"
push와 같은 작업을 배열의 앞에 실행한다. value를 배열 앞에 추가하고 새로운 길이를 반환한다.
const array = [1, 2];
array.unshift(0); // [0, 1, 2]
array.unshift(-2, -1); // [-2, -1, 0, 1, 2]
배열의 값으로 이루어진 iterator를 반환한다.
for (const value of ['a', 'b', 'c'].values()) {
console.log(value);
}
// 'a'
// 'b'
// 'c'
배열의 해당 위치 값을 대체한 새로운 배열을 반환한다.
const array = [1, 2, 0, 4, 5];
array.with(2, 3); // [1, 2, 3, 4, 5]
console.log(array); // [1, 2, 0, 4, 5]
위는 MDN 문서에서 알파벳 순으로 정렬된 순서를 따른 것이고, 비슷한 기능을 가진 메소드끼리 다음과 같이 묶어보았다.
단순한 호기심에서 시작했는데 Array의 메소드가 이렇게 많을 줄 몰랐다... at, with, flatMap 처럼 딱히 있어야 될 필요를 모르겠는 메소드도 있었지만 find, join, splice, shift 등은 유용하게 쓸 수 있을 것 같다. 다만 인자의 기본값을 잘 알고 있어야 하고, 배열을 mutate하는지 여부나 반환값이 무엇인지 등을 확실히 알고 사용해야 오류가 생기지 않을 것이다.