자바스크립트에서 배열을 다룰때 주의해야할 몇가지 내용들이 있습니다. 그 중에 가장 중요하다 생각하는건 Immutability (불변성) 입니다. 즉 원본 배열을 수정하느냐 아니면 새로운 배열을 만들어 내느냐에 대한 기본적인 이해를 바탕으로 사용해야 사이드 이펙트를 피할 수 있습니다.
원본 배열을 수정
Array.prototype.push <=> Array.prototype.pop
대표적인 배열 원본을 수정하는 메소드입니다. push 는 배열의 가장 마지막에 값을 추가하고 pop 은 가장 마지막의 값을 추출합니다.
const arr = [1, 2, 3, 4, 5]
arr.push(10) // [1, 2, 3, 4, 5, 10]
arr.pop() // [1, 2, 3, 4, 5]
Array.prototype.shift <=> Array.prototype.unshift
push 와 pop 과 반대되는 개념으로 배열의 가장 첫번째에 값을 추가하거나 제거할 수 있습니다.
const arr = [1, 2, 3, 4, 5]
arr.unshift(10) // [10, 1, 2, 3, 4, 5]
arr.shift() // [1, 2, 3, 4, 5]
Array.prototype.splice
splice 는 기존 배열에 요소를 삭제, 교체, 추가를 하는것이 가능합니다. 위에 작성된 메소드들과 다르게 원하는 index 를 지정할 수 있습니다.
const arr = [1, 2, 3, 4, 5]
arr.splice(0, 1) // [2, 3, 4, 5] - 0 번째 index 부터 1개의 요소를 추출
arr.splice(0, 1, 10) // [10, 3, 4, 5] - 0번째 index 부터 1개의 요소를 3번째 매개변수 값으로 교체
arr.splice(2, 0, 20) // [10, 3, 20, 4, 5] - 2번째 index 에 세번째 매개변수를 추가
Array.prototype.sort <=> Array.prototype.reverse
sort 와 reverse 는 원본 배열을 정렬주는 메소드입니다.
const arr = [10, 20, 1, 2, 3]
arr.sort() // [1, 10, 2, 20, 3]
arr.reverse() // [3, 20, 2, 10, 1]
정렬 메소드인데 뭔가 이상한걸 볼 수 있습니다. 분명 1 다음엔 2가 와야할것같지만 10이 오고 있습니다. 숫자의 비교가 아닌 문자비교를 하기때문에 앞자리가 같은 10이 1다음 20이 2 다음으로 오고있습니다. 정상적으로 숫자의 정렬을 위해서는 대소를 비교하여 정렬되도록 해야합니다.
arr.sort((a, b) => a - b) // [1, 2, 3, 10, 20]
원본 배열 불변성 유지
Array.prototype.map
map 메소드는 원본 배열을 순회하면서 콜백함수를 실행하고 새로운 배열을 반환하는 메소드입니다. 따라서 원본 배열의 불변성을 유지 할 수 있습니다.
const users = [
{ firstName: '홍', lastName: '길동', age: 12 },
{ firstName: '강', lastName: '호동', age: 30 },
{ firstName: '해리', lastName: '포터', age: 100 },
{ firstName: '나무', lastName: '늘보', age: 12 },
]
const userFullName = users.map(user => `${user.firstName}${user.lastName}`)
console.log(userFullName) // [ '홍길동', '강호동', '해리포터', '나무늘보' ]
console.log(users) // 원본 변화 없음
VanilsJS 로 SPA 를 구현하려고 하다보면 돔을 조작하는 api 를 많이 사용하게 되는데 이때 map 메소드가 자주 사용됩니다. 그러나 map 은 배열의 메소드로 유사배열로 취급되는 NodeList 는 배열 메소드를 사용할 수 없습니다. 그래서 배열로 취급될 수 있도록 변환하는 작업이 필요합니다.
// Array.from()
const lis = document.querySelectorAll('li');
const liArr = Array.from(lis, x => x);
Object.prototype.toString.call(lis) // [object NodeList]
Object.prototype.toString.call(liArr) // [object Array]
그래서 NodeList 객체의 프로토타입을 확인해보면
- entries: ƒ entries()
- forEach: ƒ forEach()
- item: ƒ item()
- keys: ƒ keys()
- length: (...)
- values: ƒ values()
사용가능한 프로퍼티는 이정도로 확인할 수 있습니다.
유사배열객체를 배열로 전환하는 방법에는 더 쉬운 방법이 있습니다. 전개 구문 을 활용하면 더 쉽게 배열로 만들어 사용할 수 있습니다.
const liArr = [...lis]
Array.prototype.filter
filter 메소드는 배열객체에서 원하는 항목만 추출하여 새로운 배열로 만들어 활용할 수 있습니다.
const users = [
{ firstName: '홍', lastName: '길동', age: 12 },
{ firstName: '강', lastName: '호동', age: 30 },
{ firstName: '해리', lastName: '포터', age: 100 },
{ firstName: '나무', lastName: '늘보', age: 12 },
]
const filterUsers = users.filter(user => user.age === 12)
console.log(filterUsers)
//
[
{ firstName: '홍', lastName: '길동', age: 12 },
{ firstName: '나무', lastName: '늘보', age: 12 }
]
Array.prototype.flat and reduce and concat
flat, reduce, concat 은 서로 닮아 있는 부분들이 있어서 하나의 예제에서 진행하려고 합니다.
const arr = [ 1, 2, [ 3, 4 ] ];
const arr1 = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ];
consr arr2 = [1, 2, , 4, 5]
arr.flat() // [1, 2, 3, 4]
arr1.flat() // [1, 2, 3, 4, [5, 6]]
arr1.flat(2) // [1, 2, 3, 4, 5, 6] - 2뎁스까지 하나의 배열로 병합
arr2.flat() // [1, 2, 4, 5] - 배열에 빈 공간 제거
flat 은 중첩 배열을 하나의 배열로 만들거나 배열내의 빈 공간을 제거할 수 있습니다. 이 모든것이 원본 배열은 수정하지않고 새로운 배열로 생성합니다.
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = [1, 2, 3, [4, 5]]
arr1.concat(arr2) // [1, 2, 3, 4, 5, 6]
arr1.concat(1, [2, 3]) // [1, 2, 3, 1, 2, 3]
[].concat(...arr3) // [1, 2, 3, 4, 5]
concat 은 서로 다른 배열 객체간에 병합하여 하나의 배열을 만들어 활용할 수 있습니다. 이러한 특성을 활용하여 flat 메소드와 동일한 동작을 하도록 활용할 수도 있습니다.
const arr = [1, 2, 3, 4, 5]
arr.reduce((a, b) => a + b) // 15
리듀스는 다른 메소드들과 다르게 이해하기 어렵다 라고 생각되는 부분들이 있습니다. 바로 누적이라는 개념때문인데요. 콜백함수로 넘어오는 매개변수들을 하나하나 풀어서 보고 이해하면 그리 어렵지 않게 이해할 수 있습니다.
const arr = [1, 2, 3, 4, 5]
function callback (accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue
}
arr.reduce(calback)
위 예제는 처음 작성했던것과 완전히 동일한 예제입니다. 매개변수를 하나씩 확인해보면
accumulator : 누적되어지는 매개변수입니다.
currentValue: 배열의 값들을 순차적으로 받는 매개변수입니다.
currentIndex: 현재 순회중인 배열의 인덱스값입니다.
array: 원본 배열입니다.
여기서 세번째와 네번째 매개변수값은 보통 사용하지 않고 누적매개변수와 순회중인 매개변수 두가지만 활용합니다. 그렇게 사용한것이 첫번째 예제입니다. currentValue 로 순차적으로 값을 받아와 그 값은 accumulator 에 계속 누적합산됩니다.
'프론트엔드 > Javascript' 카테고리의 다른 글
리액트 라우터 이해하기 (0) | 2021.11.15 |
---|---|
Vanila Javascript Webpack Setting (0) | 2021.10.23 |
자바스크립트 기본개념(1) - 호이스팅 (0) | 2021.10.14 |