배열 자체를 조작하는가? = 🟢
기존 배열은 건드리지 않고 조건을 적용한 새로운 배열을 반환하는가? = 🟠
splice 메서드를 사용하면 요소 추가, 삭제, 교체가 모두 가능합니다.
<script>
arr.splice(인덱스 번호[, 제거할 요소 개수, elem1, ..., elemN])
// 인덱스 번호는 제거 대상입니다.
</script>
요소 삭제하기
<script>
let arr = ["I", "study", "JavaScript"];
arr.splice(1, 1); // 인덱스 1부터(제거 대상에 포함) 요소 한 개를 제거
alert( arr ); // ["I", "JavaScript"]
</script>
요소를 삭제하고 교체하기
<script>
let arr = ["I", "study", "JavaScript", "right", "now"];
// 처음(0) 세 개(3)의 요소를 지우고, 이 자리를 다른 요소로 대체합니다.
arr.splice(0, 3, "Let's", "dance");
alert( arr ) // ["Let's", "dance", "right", "now"]
</script>
요소를 삭제하지 않고 추가하기
<script>
let arr = ["I", "study", "JavaScript"];
// 인덱스 2부터
// 0개의 요소를 삭제합니다.
// 그 후, "complex"와 "language"를 추가합니다.
arr.splice(2, 0, "complex", "language");
alert( arr ); // "I", "study", "complex", "language", "JavaScript"
// 인덱스 2부터 complex와 language를 끼워넣음
</script>
splice는 삭제된 요소로 구성된 배열을 반환할 수도 있습니다
<script>
let arr = ["I", "study", "JavaScript", "right", "now"];
// 처음 두 개의 요소를 삭제함
let removed = arr.splice(0, 2);
alert( removed ); // "I", "study" <-- 삭제된 요소로 구성된 배열
</script>
음수 인덱스도 사용 가능
<script>
let arr = [1, 2, 5];
// 인덱스 -1부터 (배열 끝에서부터 첫 번째 요소)
// 0개의 요소를 삭제하고
// 3과 4를 추가합니다.
arr.splice(-1, 0, 3, 4);
alert( arr ); // 1,2,3,4,5
</script>
객체 프로퍼티를 지우는 연산자 delete는 사용하지 않습니다.
slice는 splice와 유사해 보이지만 훨씬 간단합니다.
<script>
arr.slice([start], [end])
</script>
start와 end는 둘 다 음수일 수 있는데 이땐, 배열 끝에서부터의 요소 개수를 의미합니다.
<script>
let arr = ["t", "e", "s", "t"];
alert( arr.slice(1, 3) ); // e,s (인덱스가 1인 요소부터 인덱스가 3인 요소까지를 복사(인덱스가 3인 요소는 제외))
alert( arr.slice(-2) ); // s,t (인덱스가 -2인 요소부터 제일 끝 요소까지를 복사)
</script>
🛠️ arr.slice()는 인수를 하나도 넘기지 않고 호출하여 arr의 복사본을 만들 수 있습니다.
이런 방식은 기존의 배열을 건드리지 않으면서 배열을 조작해 새로운 배열을 만들고자 할 때 자주 사용됩니다.
<script>
arr.concat(arg1, arg2...)
</script>
메서드를 호출하면 arr에 속한 모든 요소와 arg1, arg2 등에 속한 모든 요소를 한데 모은 새로운 배열이 반환됩니다.
<script>
let arr = [1, 2];
// arr의 요소 모두와 [3,4]의 요소 모두를 한데 모은 새로운 배열이 만들어집니다.
alert( arr.concat([3, 4]) ); // 1,2,3,4
// arr의 요소 모두와 [3,4]의 요소 모두, [5,6]의 요소 모두를 모은 새로운 배열이 만들어집니다.
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6
// arr의 요소 모두와 [3,4]의 요소 모두, 5와 6을 한데 모은 새로운 배열이 만들어집니다.
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
</script>
인수 argN가 배열일 경우 배열의 모든 요소가 복사됩니다. 그렇지 않은경우(단순 값인 경우)는 인수가 그대로 복사됩니다.
concat 메서드는 제공받은 배열의 요소를 복사해 활용합니다. 객체가 인자로 넘어오면 (배열처럼 보이는 유사 배열 객체이더라도) 객체는 분해되지 않고 통으로 복사되어 더해집니다.
<script>
let arr = [1, 2];
let arrayLike = {
0: "something",
length: 1 // length 프로퍼티를 인위적으로 추가함. 유사 배열 객체입니다.
};
alert( arr.concat(arrayLike) ); // 1,2,[object Object]
</script>
인자로 받은 유사 배열 객체에 특수한 프로퍼티 Symbol.isConcatSpreadable이 있으면 concat은 이 객체를 배열처럼 취급합니다.
따라서 객체 전체가 아닌 객체 프로퍼티의 값이 더해집니다.
<script>
let arr = [1, 2];
let arrayLike = {
0: "something",
1: "else",
[Symbol.isConcatSpreadable]: true,
length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,something,else
</script>
forEach 메서드는 다음 매개변수(parameter)와 함께 배열의 각 요소에 적용하게 될 콜백 함수(callback function)를 전달합니다. 참고 블로그
순서대로
1. Current Value (명명된 매개변수) - 처리할 현재 요소(필수)
2. Index (선택적 매개변수) - 처리할 현재 요소의 인덱스
3. Array (선택적 매개변수) - forEach 메서드를 호출한 배열
우선 forEach 메서드를 사용해 배열을 순회하려면 콜백 함수 또는 익명 함수가 필요합니다.
<script>
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function() {
// code
});
</script>
콜백 함수는 각 요소에 대해 실행되며, 배열의 요소를 나타내는 매개변수를 반드시 하나 이상 사용해야 합니다.
<script>
numbers.forEach(function(number) {
console.log(number); // 1 2 3 4 5
});
</script>
필수 매개변수 다음 첫 번째 선택적 매개변수는 각 요소의 순서를 나타내는 인덱스입니다.
<script>
numbers.forEach((number, index) => {
console.log('Index: ' + index + ' Value: ' + number);
}); /**
Index: 0 Value: 1
Index: 1 Value: 2
Index: 2 Value: 3
Index: 3 Value: 4
Index: 4 Value: 5 **/
</script>
배열 매개변수는 원본 배열 그 자체입니다. 단순히 호출하기만 하면 배열의 요소 수만큼 배열이 출력되는 것을 볼 수 있습니다.
<script>
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((number, index, array) => {
console.log(array); /**
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
[1 2 3 4 5]
**/
});
// 문자열 예시
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} is at index ${index} in ${array}`);
}); /**
Bilbo is at index 0 in Billo, Gandalf, Nazgul
Gandalf is at index 1 in Billo, Gandalf, Nazgul
Nazgul is at index 2 in Billo, Gandalf, Nazgul
**/
</script>
indexOf, lastIndexOf, includes
같은 이름을 가진 문자열 메서드와 문법, 동작이 동일합니다.
연산 대상이 문자열이 아닌 배열의 요소라는 점만 다릅니다.
<script>
let arr = [1, 0, false];
alert( arr.indexOf(0) ); // 1. 요소를 발견하면 해당 요소의 인덱스를 반환
alert( arr.indexOf(false) ); // 2
alert( arr.indexOf(null) ); // -1
alert( arr.includes(1) ); // true. 해당 요소를 발견하기만 하면
</script>
위 메서드들은 요소를 찾을 때 완전 항등 연산자 === 을 사용합니다.
false를 검색하면 정확히 false만을 검색하지, 0을 검색하진 않습니다.
includes는 NaN도 제대로 처리한다는 점에서 indexOf와 차이가 있습니다.
<script> const arr = [NaN]; alert( arr.indexOf(NaN) ); // -1. NaN은 === 비교 연산자로 구분할 수 없습니다. alert( arr.includes(NaN) );// true (NaN의 여부만 확인하였습니다.) </script>
요소의 위치를 정확히 알고 싶을 때: arr.indexOf
요소가 배열 내 존재하는지 여부만 확인하고 싶을 때: arr.includes
특정 조건에 부합하는 객체를 배열 내에서 어떻게 찾을 수 있을까요?
객체로 이루어진 배열이 있다고 가정해 봅시다.
find 메서드는 함수의 반환 값을 true로 만드는 단 하나의 요소를 찾습니다.
<script>
let result = arr.find(function(item, index, array) {
// true가 반환되면 반복이 멈추고 해당 요소를 반환합니다.
// 조건에 해당하는 요소가 없으면 undefined를 반환합니다.
});
</script>
요소 전체를 대상으로 함수가 순차적으로 호출됩니다.
예시) 배열 내에서 id == 1 조건을 충족하는 사용자 객체 찾기
<script>
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"}
];
let user = users.find(item => item.id == 1);
alert(user.name); // John
</script>
위 예시에서 find 안의 함수 인자는 한 개입니다(item => item.id == 1)
다른 인자들(index, array)은 잘 사용되지 않습니다.
arr.findIndex는 find와 동일한 일을 하나, 조건에 맞는 요소를 반환하는 대신 해당 요소의 인덱스를 반환한다는 점이 다릅니다. 조건에 맞는 요소가 없으면 -1이 반환됩니다.
<script>
let users = [
{ id: 1, name: "John" },
{ id: 2, name: "Pete" },
{ id: 3, name: "Mary" },
];
let user = users.findIndex((item) => item.id == 1);
console.log(user); // 0 (id == 1의 인덱스 0을 반환)
</script>
위에서 언급한 find 메서드는 함수의 반환 값을 true로 만드는 단 하나의 요소를 찾습니다.
조건을 충족하는 요소가 여러 개라면 arr.filter(fn)를 사용하면 됩니다.
<script>
let results = arr.filter(function(item, index, array) {
// 조건을 충족하는 요소는 results에 순차적으로 더해집니다.
// 조건을 충족하는 요소가 하나도 없으면 빈 배열이 반환됩니다.
});
</script>
예시)
<script>
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"}
];
// 앞쪽 사용자 두 명을 반환합니다.
let someUsers = users.filter(item => item.id < 3);
console.log(someUsers.length); // 2
console.log(someUsers); // [ { id: 1, name: 'John' }, { id: 2, name: 'Pete' } ]
</script>
filter는 find와 문법이 유사하지만, 조건에 맞는 요소 전체를 담은 배열을 반환한다는 점에서 차이가 있습니다.