알고리즘 문제 풀이 중 원본 배열의 요소를 수정이나 삭제하기 위해서 자바스크립트 Built-in 메서드를 활용하던 중 유사 기능을 하는 splice와 slice를 알게 되었고, 뭔 차이(이름에 p가 있고 없고...)가 있길래 따로 구분되어 있는 건지 알아보았고, 자료의 파괴적 처리(Destructive)와 비파괴적 처리(Non-destructive)라는 내용을 학습하게 되어 정리 해 보았다.
파괴적 처리(Destructive)와 비파괴적 처리(Non-destructive)
자바스크립트는 자료 처리를 위해서 다양한 연산자, 함수, 메소드를 제공하는데 자료 처리 연산자, 함수, 메서드는 크게 파괴적 처리와 비파괴적 처리로 구분할 수 있다. 처리 후 원본 데이터의 상태 변화에 따라 아래와 같은 Depth로 정의하였다.
파괴적 처리: 처리 후에 원본 데이터 내용이 변경된다.
비파괴적 처리: 처리 후에 원본 데이터 내용이 변경되지 않는다.
과거에는 컴퓨터 메모리가 많이 부족했기 때문에 프로그래밍 언어와 라이브러리들은 최대한 메모리를 절약해서 사용하는 방식으로 설계되었다고 한다. 그나마 결과가 기본 자료형이면 메모리를 조금만 차지하기 때문에 원본과 결과를 모두 메모리에 저장해도 크게 무리가 없었지만, 배열처럼 크가가 어느 정도인지 모르는 대상의 원본과 결과를 모두 메모리에 저장하는 것은 꽤나 문제 발생 소지가 많기 때문에 배열과 같이 거대해질 수 있는 자료들은 메모리를 절약할 수 있게 대부분 파괴적 처리로 처리되었다. 한편으로 파괴적 처리는 메모리를 절약할 수 있다는 장점이 있긴 하지만, 원본 데이터가 사라지기 때문에 치명적인 단점이 될 수도 있다.
그래서 현재 사용되고 있는 대부분의 프로그래밍 언어는 메모리가 부족했던 과거부터 메모리가 여유로운 현재까지 계속해서 표준이 제정되고 개발되고 있고 초기에 표준화 된 것들은 파괴적 처리를 많이 했으나, 최근 표준화 된 것들은 대부분 비파괴적 처리를 한다고 한다.
자바스크립트는 현대적인 언어인 애플의 Swift 언어처럼 메소드 네이밍을 통해 어떤 메서드가 파괴적인 처리를 하는지 비파괴적인 처리를 하는지 구분하는 방법이 없기 때문에 코드를 여러 번 실행해보면서 익숙해지거나 외우는 수밖에 없는 거 같다.
Array.prototype.slice()
배열의 begin부터 end까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환하는 메서드
slice()는 원본을 대체하지 않는다. 원본 배열에서 요소의 얕은 복사본을 반환한다.
arr.slice([begin[, end]])
begin Optional
0을 시작으로 하는 추출 시작점에 대한 인덱스를 의미한다.
음수 인덱스는 배열의 끝에서부터의 길이를 나타낸다. slice(-2) 는 배열에서 마지막 두 개의 엘리먼트를 추출한다.
begin이 undefined인 경우에는, 0번 인덱스부터 slice 한다.begin이 배열의 길이보다 큰 경우에는, 빈 배열을 반환한다.
end Optional
추출을 종료 할 0 기준 인덱스. slice 는 end 인덱스를 제외하고 추출한다.
예를 들어, slice(1,4)는 두번째 요소부터 네번째 요소까지 (1, 2 및 3을 인덱스로 하는 요소) 추출한다.
음수 인덱스는 배열의 끝에서부터의 길이를 나타낸다. 예를들어 slice(2,-1) 는 세번째부터 끝에서 두번째 요소까지 추출한다.
end가 생략되면 slice()는 배열의 끝까지(arr.length) 추출한다.
만약 end 값이 배열의 길이보다 크다면, silce()는 배열의 끝까지(arr.length) 추출한다.
반환 값
추출한 요소를 포함한 새로운 배열
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2)); // Array ["camel", "duck", "elephant"]
console.log(animals.slice(1, 5)); // Array ["bison", "camel", "duck", "elephant"]
Array.prototype.splice()
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
start
배열의 변경을 시작할 인덱스로 배열의 길이보다 큰 값이라면 실제 시작 인덱스는 배열의 길이로 설정된다. 음수인 경우 배열의 끝에서부터 요소를 세어나간다.(원점 -1, 즉 -n이면 요소 끝의 n번째 요소를 가리키며 array.length - n번째 인덱스와 같음). 값의 절대값이 배열의 길이 보다 큰 경우 0으로 설정된다.
deleteCount Optional
deleteCount를 생략하거나 값이 array.length - start보다 크면 start부터의 모든 요소를 제거한다.
deleteCount가 0 이하라면 어떤 요소도 제거하지 않는다. 이 때는 최소한 하나의 새로운 요소를 지정해야 한다.
배열에서 제거할 요소의 수.
item1, item2, *...* Optional
배열에 추가할 요소. 아무 요소도 지정하지 않으면 splice()는 요소를 제거하기만 한다.
반환 값
제거한 요소를 담은 배열. 하나의 요소만 제거한 경우 길이가 1인 배열을 반환하며 아무 값도 제거하지 않았으면 빈 배열을 반환한다.
const months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
console.log(months); // ["Jan", "Feb", "March", "April", "June"]
let removed = months.splice(0, 2, 'September', 'October', 'November');
console.log(removed); // [ 'Jan', 'Feb' ]
console.log(months); // [ 'September', 'October', 'November', 'March', 'April', 'June' ]
정리: Slice 메서드와 Splice 메서드의 역할은 완벽하게 일치하진 않아 묶어 비교하긴 그렇지만 slice 메서드는 비파괴적인 처리를 하며, splice 메서드는 파괴적인 처리를 한다.
참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
Array.prototype.splice() - JavaScript | MDN
https://medium.com/@coadams9/javascript-a-few-methods-and-destructive-vs-non-destructive-c20197534ad1알고리즘
'Javascript' 카테고리의 다른 글
객체의 얕은 복사와 깊은 복사를 수행하는 방법들 (39) | 2023.11.23 |
---|---|
몫의 정수 부분만 구하는 방법들 (1) | 2023.11.23 |
배열과 객체 구조 분해 할당(destructuring assignment) (27) | 2023.11.21 |
배열과 문자열에서 중복값 제거할 수 있는 방법들 (30) | 2023.11.20 |
동기(Synchronous)와 비동기(Asynchronous) (16) | 2023.11.20 |