Array[index] 사용을 그만둬라 애송이
이 포스트는 Timotius Sitorus가 자신의 dev.to 블로그에 올린 Stop using Array[index], use Array.at() instead 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는 사견이 포함되어있기도 하다.
Array.at() 메소드는 ECMAscript2022를 통해 새롭게 추가된 Array 생성자의 프로토타입 메소드입니다. 이 메소드를 통해 우리는 마침내 JS에서 기본적으로 Negative Indexing을 처리할 수 있게 되었습니다.
Negative Indexing
네거티브 인덱싱이라 함은 음수를 인덱스로 사용하여 배열의 시작이 아닌 끝에서부터 특정 요소에 엑세스하는 기능입니다. 예를 들어 파이썬에서는 배열의 마지막 요소에 접근하고 싶은 경우 list[-1]과 같은 방식으로 작업을 수행할 수 있습니다. 그러나 JS의 array는 이런 식으로 작동하지 않습니다. 대괄호 표기법이 array나 string에 속한 것이 아니라 모든 object에 속하기 때문에 ─ 이 부분에 대해서 따로 확인해본 것은 아니지만 이러한 표기법을 지원하는 프로퍼티가 object 생성자의 prototype에 존재하는 것이 아닐까 추측한다 ─ 그렇습니다.
object에서 대괄호 표기법을 사용할 경우 해당 key를 사용하여 객체의 value를 얻는 것을 의미합니다. 배열과 문자열 역시 객체이기 때문에, 이러한 자료형들에서도 동일한 작동을 보이는 것입니다. 내부적으로 배열과 문자열은 각 요소를 현재 인덱스와 일치하는 키에 할당합니다.
// 인덱싱 방식에 관해서라면 arr는 obj와 완전히 동일하게 동작한다
const arr = ['cat', 'dog', 'fish', 'bird'];
const obj = {
0: 'cat',
1: 'dog',
2: 'fish',
3: 'bird'
};
따라서 arr[-1]은 이미 유효한 JS이지만 마지막 요소를 반환하는 것이 아닌 배열의 "-1" key에 해당하는 value를 반환하려고 시도합니다. 그리고 이러한 경우 JS는 당연하게도 ─ "-1" key가 없으니 ─ undefined를 반환하게 될 것입니다.
기존의 해결 방법
기존 JS에서는 네거티브 인덱싱을 지원하지 않지만, 이를 흉내내는 기법 몇 가지가 널리 알려져있습니다. 아마도 가장 유명한 기법은 배열의 길이에서 음수 인덱스만큼 뺀 값을 사용하는 것입니다.
const pets = ['cat', 'dog', 'fish', 'bird'];
const lastPet = pets[pets.length - 1];
console.log(lastPet); // Prints out 'bird'
대부분의 개발자가 네거티브 인덱싱을 흉내내기 위해 사용하는 기법이지만, 여기에는 몇 가지 문제가 있습니다.
- 배열의 이름이 두 번 호출되며, 일반적으로는 꽤 길어집니다.
- 변수에 할당되지 않은 배열에는 사용할 수 없습니다.
- 임시 변수에 저장하지 않는 한 함수가 리턴하는 마지막 값을 쓸 수 없습니다.
['cat', 'dog', 'fish', 'bird'][ **what do you put here** - 1];
const a = () => ['cat', 'dog', 'fish', 'bird'];
a()[ **What do you out here** - 1];
다른 방식으로는 Array.slice() 메소드가 네거티브 인덱싱을 지원한다는 점을 이용할 수 있습니다.
const pets = ['cat', 'dog', 'fish', 'bird'];
const lastPet = pets.slice(-1)[0];
console.log(lastPet); // Prints out 'bird'
이 방법은 앞서 언급한 많은 문제를 해결하지만, 몇 가지 새로운 문제를 일으킵니다.
- 구문을 직관적으로 이해하는 데 어려움이 있습니다. 특히 네거티브 인덱싱으로 slice된 array에 [0]이 꼬리를 물고 붙어있다는 점이 그렇습니다.
- 지정한 인덱스로부터 배열의 끝까지가 임시 배열을 이루게 됩니다. 이는 [0]을 통해 원하는 item을 리턴한 이후 메모리 힙에서 즉시 삭제됩니다.
Array.at()
at 메소드는 위에서 언급한 다양한 문제를 해결하기 위해 구현되었습니다. 아규먼트로 양수를 넣을 경우 Array[index]와 정확히 동일한 작동을 보장하면서, 아규먼트로 음수를 넣는 경우에는 네거티브 인덱싱을 완벽하게 구현해냅니다.
const pets = ['cat', 'dog', 'fish', 'bird'];
const lastPet = pets.at(-1);
console.log(lastPet); // Prints out 'bird'
이 메소드를 사용하므로써 네거티브 인덱싱을 흉내내는 이전의 방식들을 대체할 수 있으며, 더 깔끔한 구문을 제공하며, 성능 저하가 발생하지도 않습니다. 필요한 경우 polyfill을 사용할 수 있는 대부분의 최신 브라우저에서 at 메소드를 사용할 수 있습니다.
+ 자바스크립트는 불합리하다 포스트에서 나는 "배열은 음의 인덱스를 허용하지 않으면서 splice에서는 허용하고 있는 걸까?"하는 궁금증이 있었는데, 이와 관련해서 찾아보다가 at 메소드의 존재에 대해 알게 되었다. 추가적으로 배열에서 대괄호 표기법을 이용해 음의 인덱스에 접근할 시 undefined가 반환되는 이유도 이 게시물을 통해 처음 알게 되었다.
블로그의 정보
Ayden's journal
Beard Weard Ayden