원본: pop and push: Learning Javascript’s Array Methods
이 포스트에서는 배열에 항목을 추가하는 push() 메소드와 항목을 제거하는 pop() 메소드에 대해 알아보겠습니다.
Table of Contents
push pop 작동 방식
배열의 끝에 항목을 추가하려면 push() 메소드를 사용하고 배열의 끝에서 항목을 제거하려면 pop() 메소드를 사용합니다.
개발자 도구에서 다음의 예제 코드를 입력하고 console.log() 메소드를 통해 테스트할 수 있습니다.
const numbers = [1, 2, 3, 4];
numbers.push(5);
console.log(numbers);
numbers.pop();
console.log(numbers);
여기서는 push() 메소드를 사용하여 numbers 배열에 ‘5’ 라는 항목을 배열의 끝에 추가했습니다. 바로 다음 pop() 메소드를 사용하여 방금 추가한 항목을 제거했습니다.
배열의 시작 부분에서 항목을 추가/제거 하려면 shift() 메소드와 unshift() 메소드를 사용할 수 있습니다.
push 안쓰고 항목 추가하기
이 메소드를 쓰지 않고 어떻게 배열의 끝에 항목을 추가할 수 있을까요? 가장 쉬운 방법은 배열 내의 인덱스 위치에 값을 할당하는 것 입니다:
const numbers = [1, 2, 3, 4];
numbers[numbers.length] = 5;
console.log(numbers);
다른 프로그래밍 언어에서는 이런 접근을 허용하지 않습니다. 일반적으로 배열은 고정된 길이를 가지며 실제로는 더 긴 새로운 배열을 다시 만드는 것 입니다.
자바스크립트는 대부분 이러한 작업을 허용합니다. 하지만 이 방법에는 두 가지 제한사항이 있습니다.
첫째, 이제 이 배열의 인덱스는 수동으로 관리해야 합니다. 따라서 코드를 더블체크하여 어디선가 인덱스를 놓치거나 잘못한 것은 없는지 확인해야 합니다. 둘째, 원본 배열을 변경하는 방법이므로 새로운 배열을 만들고 싶을 때는 다른 방법을 사용해야 합니다.
새로운 배열을 만드려면 새로운 항목과 스프레드 연산자를 사용할 수 있습니다. 스프레드 연산자를 사용하면 동일한 동작을 하는 나만의 배열 추가 메소드를 만들 수 있습니다.
실제로 이를 구현하려면 array와 item을 매개변수로 받는 함수를 정의해야 합니다. 그 다음 원본 배열의 모든 값과 새 항목이 포함된 새 배열을 리턴하면 됩니다:
function myPush(array, item) {
return [...array, item];
}
이제 numbers 배열에 다음과 같이 항목을 추가할 수 있게되었습니다:
let numbers = [1, 2, 3, 4];
numbers = myPush(numbers, 5);
이 구현은 잘 작동하지만 한가지 기능이 빠져있습니다. 내장 push() 메소드는 한 번에 여러 값을 추가할 수 있기 때문입니다.
const numbers = [1, 2, 3, 4];
numbers.push(5, 6, 7);
console.log(numbers);
위의 요구사항을 충족하여 push() 메소드와 동일한 기능을 하는 함수를 구현하려면 spread, rest 연산자를 사용하여 수정할 수 있습니다.
function myPush(array, ...items) {
return [...array, ...items];
}
수정한 myPush() 함수는 매개변수 부분에서 items 변수로 여러 개의 인수를 가져와 기존의 배열에 병합합니다.
이제 나만의 함수를 사용해 여러 개의 값을 한번에 추가할 수 있습니다:
let numbers = [1, 2, 3, 4];
numbers = myPush(numbers, 5);
console.log(numbers);
numbers = myPush(numbers, 6, 7, 8);
console.log(numbers);
pop 안쓰고 항목 제거하기
pop() 메소드를 사용하지 않고 배열의 마지막 항목을 제거하는 것은 약간 까다롭습니다. 가장 좋은 방법은 상황에 따라 다르며 다른 배열 메소드를 같이 사용해야할 수도 있습니다.
다음은 생각처럼 잘 작동하지 않는 접근 방법, 잘 작동하는 접근 방법, 개인적으로 가장 좋다고 생각되는 접근 방법을 설명하겠습니다.
delete 키워드 사용
먼저 delete 키워드를 사용하는 접근 방법입니다.
이 방법은 되도록 사용하지 않는 것이 좋습니다. 이는 배열에서 값을 삭제하기는 하지만 배열의 길이는 이전과 동일하게 유지되고 삭제된 항목 대신 빈 항목이 자리하게 됩니다.
const numbers = [1, 2, 3, 4];
console.log(numbers.length);
delete numbers[numbers.length - 1];
console.log(numbers.length);
console.log(numbers);
나중에 이 배열에서 루프를 돌면 항목의 수 만큼 루프 돌지 않게 되며 디버깅하기 어려운 동작을 하게 됩니다.
for 문 사용
배열에서 항목을 지우는 또 다른 방법은 다음과 같이 for 문을 사용하여 새로운 배열을 만드는 것 입니다:
function myPop(array) {
let res = [];
for (let i = 0; i < array.length - 1; i++) {
res[i] = array[i];
}
return res;
}
myPop() 함수에서는 새로운 배열을 만들고 원본 배열에서 루프를 돌며 마지막 항목만 빼고 새 배열에 복사합니다.
이는 잘 작동합니다.
let numbers = [1, 2, 3, 4];
numbers = myPop(numbers);
이를 응용하면 모든 배열 메소드는 for 문으로 구현할 수 있습니다.
하지만 모든 부분에 명명된 메소드가 아닌 for 문을 사용하는 것은 피해야 합니다. 왜냐하면 모든 부분에 for 문을 쓰면 코드가 더 읽기 어려워지기 때문입니다.
slice 메소드 사용
Array.slice() 메소드를 사용하면 for 문을 사용하지 않고 목표를 달성할 수 있습니다.
주의할 점은 slice() 메소드와 splice() 메소드의 차이점을 구분하는 것 입니다.
다음과 같이 slice() 메소드를 사용하면 pop() 메소드를 간단하게 구현할 수 있습니다:
function myPop(array) {
return array.slice(0, array.length - 1);
}
위의 함수는 원본 배열 시작부분 부터 마지막 항목의 이전 항목 까지에 해당하는 shallow copy를 리턴합니다.
이렇게 하면 pop() 메소드와 동일한 기능을 사용할 수 있습니다:
let numbers = [1, 2, 3, 4];
numbers = myPop(numbers);
console.log(numbers);
numbers = myPop(numbers);
console.log(numbers);
numbers = myPop(numbers);
console.log(numbers);
pop() 메소드를 사용하지 않고 배열의 마지막 항목을 제거하는 방법 중 slice() 메소드를 사용하는 것이 가장 좋습니다.