sbyeol3/articles

[번역] JavaScript의 새로운 `.at()` 메소드 사용하기

Opened this issue · 0 comments

원문 : Using the new JavaScript .at() method을 읽고 번역한 글입니다.

자바스크립트의 .at() 메소드는 인덱스를 기반으로 엘리먼트를 선택할 수 있도록 하기 위해 ECMA 인터내셔널 TC39의 8월 릴리즈에서 소개되었습니다.

자바스크립트에서 엘리먼트를 선택하는 것은 개발하는 데 있어 흔하게 발생하는 일이지만, .at() 메소드가 나타나기 전까지 자바스크립트는 배열의 처음이나 끝 또는 문자열 내에서 엘리먼트나 문자를 선택하는 메소드와 기술만 존재했습니다.

대괄호 표기인 []는 보통 특정 인덱스의 엘리먼트를 가져올 때 사용되는데, 이는 단점이 있습니다. 예를 들어 배열의 마지막 아이템에 접근하기 위해 파이썬과 같은 언어에서 보이는 것처럼 arr[-1]과 같이 음수의 인덱스를 사용할 수 없습니다.

그 결과 개발자들은 slice() 메소드와 length 프로퍼티를 사용하여 배열의 끝에 있는 아이템을 선택합니다. 그럼에도 이 방법 또한 단점이 있습니다.

이 튜토리얼에서는 .at() 메소드와 사용하는 방법에 대해 살펴보고 이미 존재하는 방법과 비교하여 얼마나 더 나아졌는지 또한 알아보겠습니다.

인덱싱 가능한 객체 프로토타입

.at() 메소드는 인덱싱 가능한 객체의 prototype에 위치합니다.

인덱스 항목을 표현할 수 있는 이 객체들은 Array, String, TypedArray와 같은 클래스를 포함하는데, 또한 각 클래스는 Array.prototype.at(), String.prototype.at(), TypedArray.prototype.at()를 가지고 있으므로
인덱싱 가능한 객체에서 바로 .at() 메소드를 사용할 수 있습니다.

배열의 요소를 가져오기 위한 기존 방법

.at() 메소드의 장점을 보기 위해 비교의 목적으로 기존의 방법들에 대해 빠르게 살펴보겠습니다. 이는 입문자들에게도 다시금 환기하는 역할도 해줄 것입니다.

arr이라는 배열이 있다고 해봅시다.

const arr = [1, 2, "three", 4, 5, true, false];

대괄호 []을 사용하여 arr 배열에서 특정 인덱스의 요소를 가져올 수 있습니다. 예를 들어 arr[0]은 첫 번째 요소인 1을 가져오겠죠. 그러나 배열의 길이를 알 수 없는 상황이라면 length 프로퍼티나 slice() 메소드를 사용해야 할 것입니다.

length 프로퍼티 사용하기

length 프로퍼티를 사용하는 방법은 아래와 같습니다.

arr[arr.length - N];

여기서 N은 배열의 끝에서부터 n번째 요소를 가져온다는 것과 같습니다. 또한 이 방법을 통해 배열의 끝에서부터 배열의 요소를 선택할 수 있습니다.

아래 코드에서 이 방법으로 arr 배열의 마지막 요소를 가져와보겠습니다.

const arr = [1, 2, "three", 4, 5, true, false];
const lastItem = arr[arr.length - 1];
console.log(lastItem);  // Expected Output: false

이 방법은 잘 작동하지만 간단한 작업에 비해 문법이 불편하고 썩 좋지는 않습니다. 게다가 함수의 리턴값을 사용할 때 리턴값을 변수에 저장해야 한다는 단점이 있습니다.

function appendNumber(arr, N) {
  arr.push(N);
  return arr;
}

const tempArr = appendNumber([1, 2, "three", 4, 5, true, false], 6);
console.log(tempArr[tempArr.length - 1]); // Expected Output: 6

위 코드에서 appendNumber() 함수의 반환값은 length 프로퍼티를 적용하기 전에 먼저 tempArr에 저장되어야 합니다.

slice() 메소드 사용하기

개발자는 배열의 마지막 요소를 가져오기 위해 아래와 같이 slice() 메소드를 사용할 수도 있습니다.

arr.slice(-1)[0]

이 문법은 음수 인덱스를 허용하는데 추후에 나오는 .at() 메소드에서도 볼 수 있습니다.
음수 인덱스는 배열의 끝에서 부터의 오프셋을 나타냅니다. 예를 들어 slice(-1)은 뒤에서부터 마지막 아이템을 제거하여 새로운 배열로 반환합니다. slice(-2)는 마찬가지로 마지막 2개를 제거합니다.

그러나 여기에 초점은 마지막 요소이기 때문에 [0]은 마지막 요소를 선택하게 됩니다.
이 문법을 사용하여 arr 배열의 마지막 요소를 가져올 수 있습니다.

const arr = [1, 2, "three", 4, 5, true, false];

console.log(arr.slice(-1)[0]); // Expected Output: false

위에서 봤던 length 프로퍼티와 다르게 이 방법은 해당 문법을 사용하기 위해 함수의 반환값을 저장해야 할 필요는 없습니다.
그래서 좀 더 유연한 방법입니다.

function appendNumber(arr, N) {
  arr.push(N);
  return arr;
}

console.log(appendNumber([1, 2, "three", 4, 5, true, false], 6).slice(-1)[0]); // 6

그럼에도 불구하고 이 문법은 이상하게 보이고 개발자의 의도를 명확하게 보여주지 않습니다. 또한 불편할 수도 있고요.

arr[-1]로 마지막 요소에 접근할 수 없는가?

이 질문은 자바스크립트를 처음 사용하는 사람들이 흔하게 제기하는 질문입니다. 특히 Python과 같은 언어를 사용했던 사람들이죠.
자바스크립트에서 arr[-1]과 같은 표기는 유효한 객체 프로퍼티입니다. 자바스크립트에서 배열을 포함한 모든 것은 객체입니다.
그래서 언제든지 우리는 arr[0]과 같은 대괄호 표기를 사용할 수 있습니다. 이는 객체의 프로퍼티 중 0이라는 키를 가지는 프로퍼티를 참조하는 것입니다.

객체 표기 방법으로 arr 를 다시 작성해본다면 아래와 같을 겁니다.

const arr = {
  0: 1,
  1: 2,
  3: "three",
  // ...
};

console.log(arr[0]); // Expected Output: 1

위 코드에서 -1을 key로 가지는 값은 존재하지 않습니다. 그래서 arr[-1]undefined를 반환할 겁니다.
만약 아래와 같이 객체 프로퍼티 중에 -1 key가 존재한다면 그에 해당하는 값을 반환합니다.

const arr = {
  "-1": "valid"
};

console.log(arr[-1]); // Expected Output: valid

즉, 이미 해당 문법은 유효한 문법이기 때문에 마지막 요소를 가져오는 방법으로 arr[-1] 표기를 사용할 수 없다는 뜻입니다.
배열의 끝에서부터 요소를 가져오기 위해 음수의 인덱스를 사용하려면 .at() 메소드를 사용해야 합니다.

.at() 문법

.at() 메소드는 리턴받을 요소의 인덱스를 파라미터로 받습니다. 음수 인덱스를 받으면 배열이나 문자열의 뒤에서부터 인덱스를 세어 해당 요소나 문자를 반환하거나 undefined를 반환합니다.

at(index)

.at() 메소드 사용하기

위에서 언급했던 것처럼 .at()는 반환받을 요소의 인덱스를 받습니다. 이 섹션에서는 유즈케이스를 살펴보겠습니다.
arr 배열로 다시 올라가 어떻게 .at() 메소드를 사용하여 각 요소를 반환받는지 봅시다.

const arr = [1, 2, "three", 4, 5, true, false];

console.log(arr.at(0)); // Expected Output: 1
console.log(arr.at(2)); // Expected Output: "three"
console.log(arr.at(-1)); // Expected Output: false
console.log(arr.at(-3)); // Expected Output: 5

.at() 메소드에 양수 인덱스를 전달하면, 메소드는 해당 인덱스를 가지는 요소를 반환합니다. 음수의 인덱스인 경우에는 배열의 끝에서부터의 인덱스에 해당하는 요소를 반환합니다. 위 코드에서 at(-1)는 배열의 끝에서부터 1개를 세어 false를 반환합니다. 같은 방식으로 at(-3)은 끝에서부터 세번째에 있는 5를 반환합니다.

문자열에서도 배열과 같은 방식으로 동작합니다.

const str = "The last alphabet is z";

console.log(str.at(0)); // Expected Output: T
console.log(str.at(-1)); // Expected Output: z

이 메소드는 사용하기에 아주 좋습니다. at(-1)을 사용하여 문자열에서 가장 끝에 있는 문자를 얻을 수 있습니다.
동일한 동작을 length 프로퍼티를 이용한다면 문법은 더욱 복잡해집니다.

console.log(str[str.length - 1]); // Expected Output: z

함수의 반환값 사용하기

length 프로퍼티를 사용할 때와 다르게 at() 메소드는 함수의 반환값을 사용하기 전에 저장해야 할 필요는 없습니다.
다음은 배열에 마지막으로 삽입된 요소를 출력하는 코드입니다.

function appendNumber(arr, N) {
  arr.push(N);
  return arr;
}

console.log(appendNumber([1, 2, "three", 4, 5, true, false], 6).at(-1));
// Expected Output: 6

코드에서 .at() 메소드는 반환된 값에 바로 적용되어 변수에 값을 저장하지 않아도 됩니다.
아래 코드를 살펴봅시다.

const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr.at(0.6)); // Expected Output: 1
console.log(arr.at(-3.6)); // Expected Output: 5

위 코드에서 첫 번째 출력은 0 인덱스에 해당하는 요소이지만 두 번째 출력은 끝에서부터 세 번째 요소입니다.
이것은 무작위로 배열의 요소를 선택하고 싶을 때 꽤 유용합니다. 이를 가위바위보 게임 프로젝트로 설명해보겠습니다.
컴퓨터에서 랜덤으로 선택하기 위해 .at() 메소드를 사용할 수 있습니다.

아래 코드는 메소드를 사용하여 어떻게 컴퓨터가 무작위로 선택하는 방법을 보여줍니다.

const computerOptions = ["rock", "paper", "scissors"];
const randomIndex = Math.random() * computerOptions.length;

console.log(computerOptions.at(randomIndex));

Math.random()을 사용하면 0 이상 배열 길이 미만 사이의 수를 얻습니다.
.at() 메소드가 인덱스로 부동소수점 수를 받게되면 소수점 앞의 수를 고려하여 해당 인덱스의 요소를 반환합니다.

같은 동작을 하기 위해 대괄호를 사용한다면 floor 메소드를 사용하여 가까운 정수로 변환하지 않는 한 불가능합니다.

const computerOptions = ["rock", "paper", "scissors"];
const randomIndex = Math.random() * computerOptions.length;

console.log(computerOptions.at(randomIndex));

대괄호 표기방식은 해당 수를 가지는 값이 없으므로 undefined를 반환하기 때문입니다.

const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr[0.6]); // Expected Output: undefined

.at() 메소드는 Math.floor를 사용하여 랜덤 수를 내림하는 단계를 거치지 않게 해줍니다.

브라우저 지원

이 튜토리얼을 작성할 시점을 기준으로 .at() 메소드는 극히 일부를 제외한 대부분의 모던 브라우저에서 꽤 잘 작동합니다.
브라우저 지원은 여기를 참고하세요.

image

결론

.at() 메소드는 이 튜토리얼에서 봤듯이 인덱스로부터 요소를 가져오는 것을 더 편하게 해줍니다.
또한 이미 존재하는 방법들과 비교했을 때 더욱 간결하다는 장점이 있습니다.