
저는 알고리즘 문제, 코드를 작성할 때 지피티에게 좀 더 효율적인 방법이 없는지, 가독성이 떨어지는 부분이 있는지 코드리뷰를 부탁하는데요. 그럴 때 보면 아는 메소드인데 저도 모르게 익숙한 방법을 많이 쓰는걸 깨달았습니다. 그래서 배열 메소드를 조금 정리해볼까 합니다.
자바스크립트에서 배열 제일 마지막 요소를 접근할 때 보통 어떻게 하시나요?
const array = [];
array[array.length - 1];
이렇게 하시나요? 직관적이고 좋지만 배열 변수명이 길거나 하면 코드가 길어져 가독성이 다소 떨어져보일 것 같기도 합니다
그래서 나온 at 메소드!
at 메소드는 정수값을 받아 해당 인덱스에 있는 값을 반환하며, 양수와 음수가 모두 가능합니다. 음수로도 가능하다? 무슨 말일까요?
바로 음수는 배열의 마지막 요소 부터 거슬러 접근이 가능하다는 말입니다!
그럼 위의 코드를 어떻게 at메소드로 바꿀 수 있을까요?
const array = [];
array.at(-1);
조금 멋져진 것 같습니다! 간결하고 가독성도 좀 더 좋아졌어요.
index < 0인 경우, index + array.length로 접근하여 -1을 넘겨주면 배열의 마지막 요소가 반환됩니다.
인덱스가 음수가 아니면 대괄호 표기법과 동일합니다.
fill() 메서드는 배열의 인덱스 범위 내에 있는 모든 요소를 정적 값으로 변경합니다.
그리고 수정된 배열을 반환합니다.
정적 값이란? 함수처럼 매번 계산해서 다른 걸 넣는 게 아니라, 주어진 값 그대로 반복해서 채우는 것. 원시 값이면 문제가 없지만 참조형 값(객체, 배열)일 때는 주의가 필요합니다.
만약 dp 배열을 만들고 모든 값을 false로 초기화하고 싶다면?
const n = 10;
const dp = new Array(n);
for (let i = 0; i < n; i++) dp[i] = false;
이런 방법도 있지만! fill() 메소드를 쓴다면?
const n = 10;
const dp = Array(n).fill(false);
좀 더 직관적이고 간결해졌습니다! 그러면 참조형 값인 배열일 때는 어떻게 될까요?
const n = 10;
const dp = Array(n).fill([]);
dp[0].push(1);
console.log(dp);
// [ [1], [1], [1], [1], [1], [1], [1], [1], [1], [1] ]
fill([])에서 [] 배열 하나만 생성되고 그리고 그 하나의 배열 참조(주소)가 dp의 모든 칸에 복사됩니다.
그래서 dp[0]을 수정하면 사실은 같은 배열을 참조하고 있는 dp[1] ~ dp[9]도 똑같이 변경됩니다.
그럼 어떻게 하면 서로 각각의 배열을 가지도록 할 수 있을까요?
const n = 3;
const dp = Array(n).fill().map(() => []);
이렇게 하면 map의 콜백이 호출될 때마다 새로운 배열이 생성되기 때문에 인덱스별로 서로 다른 배열을 가질 수 있습니다.
fill() 메소드는 물론 새로운 배열이 아닌 기존 배열에서도 사용할 수 있습니다.
const array = [1, 2, 3, 4];
const array2 = array.fill(0, 0, 1);
console.log(array2) // [0, 2, 3, 4]
fill(채울 값, 시작 인덱스, 끝나기 직전 인덱스)로 수정된 배열을 반환합니다.
(기존 배열 수정X)
Array.from()은 fill()이랑 다르게 배열이나 유사 배열(array-like, iterable)을 새 배열로 변환하거나, 변환하면서 각 요소를 가공할 수 있는 메서드입니다.
사용법
Array.from(arrayLike, mapFn, thisArg)
arrayLike → 배열처럼 length 속성이 있거나, 이터러블(Set, Map, 문자열 등)
mapFn (옵션) → 각 요소를 변환하는 함수
thisArg (옵션) → mapFn 실행 시 this로 쓸 값
mapFn을 배열 초기화를 하는 예시
const arr = Array.from({ length: 5 }, (_, i) => i * 2);
console.log(arr);
// [0, 2, 4, 6, 8]
그럼 fill() 대신 from()을 써서 dp 배열도 초기화할 수 있을 것 같습니다.
const dp = Array.from({ length: 3 }, () => []);
dp[0].push(1);
console.log(dp);
// [ [1], [], [] ]
thisArg는 그럼 어떻게 쓰나요?
const obj = { multiplier: 10 };
const arr = Array.from([1, 2, 3], function (x) {
return x * this.multiplier;
}, obj);
console.log(arr); // [10, 20, 30]
thisArg에 obj를 넘겼으므로 mapFn 안에서 this.multiplier는 10이 되고 arr을 저런 결과를 갖게 됩니다.
++ 화살표 함수는 this 바인딩을 하지 않기 때문에 무시되므로 function 키워드 사용은 필수😉
요것은 다음 포스팅으로 남겨보겠습니다.
조금이라도 도움이 되었길 바라봅니다. 읽어주셔서 감사합니다!