본문 바로가기

언어/JavaScript

[JavaScript][강력 추천] slice(), splice() [엄탱][배열 내장함수#5]

728x90

해당 글은 기존에 작성한 JavaScript 글 제목이 변경되지 않아 다시 올리게 된 글입니다.

 

오늘은 JS 배열 내장함수 slice, splice에 대해서 준비해 봤습니다.

하루에 계획한 것을 하기 위해서 하루에 하나의 개념만 다루려고 했는데요.

slice와 splice는 같이 다뤄야 할 것 같아서 같이 준비했습니다!

 

이 글을 보시면 slice splice에 대해서 알고 싶은 분들 확실하게 이해하고 주의사항도 알아갈 수 있습니다.

꼭 보시길 추천 드립니다.

 

자! 그럼 시작하겠습니다!

slice, splice 간단 한 줄 정리

  • slice: 배열의 원하는 시작점부터 원하는 마지막 시점까지 값에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다. 원본 배열은 바뀌지 않습니다. (주의할 점! 각각의 값은 얕은 복사이기 때문에 배열 요소 중 참조형 데이터는 수정하면 같이 변경이 됩니다. 아래에 자세히 설명했으니 참고 부탁드립니다)
  • splice: 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 기존 배열의 내용을 변경하고 삭제한 데이터들을 배열로 반환합니다.
여기서 잠깐!!!
얕은 복사가 뭐야?? 하시는 분들을 위해 간략히 준비해 봤습니다.

얕은 복사: 참조(주소) 값을 복사합니다. 
얕은 복사: 주소를 복사해 오기 때문에 메모리를 공유합니다. 하나의 객체(참조형)를 변경하면 두 개의 객체(참조형) 모두 값이 동일하게 변경됩니다.

깊은 복사: 값을 복사합니다. 즉, 주소 값 메모리에 깊이 들어가 값을 복사하는 느낌이라고 말하면 더 기억하기 좋을까요??
깊은 복사: 값을 복사해 오기 때문에, 독립 적인 메모리에 값을 할당하게 됩니다. 

또한, 변수는 기본형과 참조형이 있는데, 기본형은 값을 담고 있고 참조형은 값을 갖고 있는 메모리의 주소 값을 갖고 있습니다.

그래서 기본형은 얕은 복사를 한다고 하더라도 값 자체가 복사되기 때문에 의미가 없습니다! 즉, 기본형은 얕은, 깊은 복사의 의미가 없고 참조형만 의미가 있습니다.

추후에 얕은 복사, 깊은 복사에 대해서 포스팅 후에 링크를 추가하도록 하겠습니다.

 

그런데 여기서 한 가지 의문이 듭니다.. 도대체 왜?? slice는 얕은 복사인데 왜 원본 배열이 바뀌지 않는 것일까요??

이 부분은 바로 밑에 정의에서 설명드리겠습니다!

 

slice, splice 정의

역시나 사전적인 의미를 먼저 알아보겠습니다 :)

  • slice: 썰다, 베다
  • splice: (밧줄의 두 끝을) 잇다, (필름 테이프 등의 두 끝을) 붙이다

그렇다면 MDN 사이트에서는 어떻게 설명을 했을까요?

MDN

slice() 메서드는 어떤 배열의 begin부터 end까지 (end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다. 원본 배열은 바뀌지 않습니다.

splice() 메서드는 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경합니다.
 

Array.prototype.slice() - JavaScript | MDN

slice() 메서드는 어떤 배열의 begin부터 end까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다. 원본 배열은 바뀌지 않습니다.

developer.mozilla.org

 

slice

const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
 
console.log(animals.slice(2)); //["camel", "duck", "elephant"]
console.log(animals.slice(2, 4)); //["camel", "duck"]
console.log(animals.slice(1, 5)); //["bison", "camel", "duck", "elephant"]
console.log(animals.slice(-2)); //["duck", "elephant"]
console.log(animals.slice(2, -1)); //["camel", "duck"]
console.log(animals.slice()); //["ant", "bison", "camel", "duck", "elephant"]

위의 예제와 MDN 사이트의 정의와 사전적인 의미로 보아 slice는 기존 배열은 변경하지 않고 기존 배열에서 원하는 데이터를 잘라내어 잘라낸 데이터들을 새로운 배열에 담아 반환하는 것을 알 수 있습니다.

 

여기서, 위에서 생각한 의문에 대해서 짚고 넘어가겠습니다. 

 

slice() 주의사항

도대체 왜?? slice는 얕은 복사인데 왜 원본 배열이 바뀌지 않는다고 하는 것일까요??

 

배열 A를 slice를 한다고 하면, 각각의 배열 A의 요소들을 얕은 복사한다는 의미이고, 배열 A의 길이 자체는 바뀌지 않는 다고 하는 것입니다. 하지만, 배열 A를 slice 한 배열 B의 값을 변경한다면 각각의 값은 얕은 복사를 했기 때문에 배열 A의 값은 변경될 수 있습니다.

 

밑에 제가 작성한 예제를 한번 살펴보겠습니다.


기본형 데이터를 갖는 배열

위의 예제를 보시면 animals와 animalsSlice1의 배열은 서로 독립적으로 보입니다.

 

참고로 위에서 설명드렸지만, 기본형 변수는 얕은 복사의 의미가 없습니다.


참조형 데이터를 갖는 배열 (1)

 

하지만, 위의 예제에서 objects와 objectsSlice1의 배열은 값이 동시에 변하는 것을 볼 수 있습니다.

 

이유는 생각보다 간단합니다.
slice는 배열을 얕은 복사 하는 게 아니라 각각의 값들을 얕은 복사 해서 새로운 배열에 담고 해당 배열을 리턴해줍니다.

 

혹여나 slice는 원본 배열이 변경 안된다 해서 막 사용하시다가 위와 같은 상황이 발생하지 않게 꼭 주의해 주세요!!!

 

Array.prototype.slice() 로직이 궁금하시다면 >>> ECMA 표준을 정의한 사이트 접속


참조형 데이터를 갖는 배열 (2)

하지만 위와 같이 데이터를 변경하게 되면 objectsSlice1 [0]에 '새로운 메모리 주소 값'이 할당되어 objects [0]와 독립적인 데이터가 됩니다.

 

splice

const months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months); //["Jan", "Feb", "March", "April", "June"]
 
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months); //["Jan", "Feb", "March", "April", "May"]

위의 예제와 MDN 사이트의 정의와 사전적인 의미로 보아 splice는 기존 배열의 원하는 곳에 데이터를 추가하거나 잘라내고 잘라낸 곳에 데이터를 추가하고 나서 잘라낸 곳을 이어 주어 기존 배열의 값을 변경시키고 위에 따로 내용은 없지만, splice는 제거한 요소를 담은 배열을 반환합니다.

 

각각의 보충 설명은 사용방법에서 설명을 하겠습니다.

 

slice() 사용법

다음은 slice() 함수 구문입니다. [] 안에 들어간 건 선택입니다.

arr.slice([*begin*[, *end*]])

begin (선택)

  • 배열에서 추출 시작점에 대한 인덱스를 의미합니다.
    즉, 난 A배열에서 begin부터 추출할 거야~라는 의미입니다!
  • begin은 음수도 가능합니다. 음수 인덱스는 거꾸로 배열의 끝에서부터 길이를 나타냅니다.
    예를 들어, slice(-2)는 배열에서 마지막 두 개의 엘리먼트를 추출합니다.
  • begin을 정의하지 않으면 begin은 자동으로 0으로 정의됩니다.
  • begin이 배열의 길이보다 큰 경우에는, 빈 배열을 반환합니다.

end (선택)

  • 배열에서 추출을 종료할 기준 인덱스입니다.
    slice는 end 인덱스를 제외하고 추출합니다.
    예를 들어, slice(1, 4)는 두 번째 요소부터 네 번째 요소까지 (1, 2, 3 인덱스의 요소) 추출합니다.
  • 음수 인덱스는 배열의 끝에서부터의 길이를 나타냅니다.
    예를 들어, slice(2, -1)는 세 번째부터 끝에서 두 번째 요소까지 추출합니다.
  • end가 생략되거나 end 값이 배열의 길이보다 크다면, slice()는 배열의 끝까지 추출합니다.

사용법은 간단합니다! 위의 내용을 참고하셔서 slice 함수의 인자 값에 시작 인덱스, 끝 인덱스만 넣어주시면 됩니다!

참고로 시작, 끝 인덱스가 양수로 가정하고 반환되는 값들은 시작 인덱스 이상!!! 끝 인덱스 미만!!!입니다.

 

위의 예제를 보시면 animals 배열을 아무리 slice를 해도 기존 배열은 그대로 인 것을 확인할 수 있습니다.

 

 

splice() 사용법

다음은 splice() 함수 구문입니다.

array.splice(start [, deleteCount [, item1 [, item2 [,...]]]])

start (필수)

  • 배열의 변경을 시작할 인덱스입니다.
  • 배열의 길이보다 큰 값이라면 실제 시작 인덱스는 배열의 길이로 설정됩니다.
  • 음수인 경우 끝에서부터 요소를 새어 나갑니다.
    단, 절댓값이 배열의 길이보다 크면 0으로 설정됩니다.

deleteCount (선택)

  • 배열에서 제거할 요소의 수입니다.
  • 생략하거나 array.length - start 보다 크면 start부터의 모든 요소를 제거합니다.
  • 0 이하라면 어떤 요소도 제거하지 않습니다.

items1, item2, … (선택)

  • 배열에 추가할 요소입니다.
  • 요소를 지정하지 않으면 splice는 요소를 제거하기만 합니다.

 

splice도 사용법은 간단합니다.
위의 내용을 참고해서 splice 함수의 인자 값에 시작 인덱스, 삭제할 개수, 추가할 데이터만 넣어 주시면 됩니다.

 

위의 예제를 보시면 splice는 기존 배열을 변형시키고 삭제된 데이터를 반환합니다.
만약 아무것도 제거하지 않았으면 빈 배열을 반환합니다.

 

MDN 사이트에 예제가 많으니 혹시 더 필요하신 분들은 splice-MDN사이트를 클릭해 주세요 :)

 

slice()와 splice()의 차이점

제가 생각할 때 slice와 splice의 가장 중요한 게 차이점이라고 생각합니다!

  • slice는 기존 배열을 변경하지 않지만, splice는 기존 배열이 변경됩니다.
  • slice는 배열에서 원하는 데이터만 추출하는 게 목적이지만,
    splice는 해당 배열을 원하는 데이터를 추가, 수정, 삭제가 목적입니다.
  • slice는 두 번째 인자가 종료 인덱스이지만, splice는 두 번째 인자가 삭제 개수입니다.

slice(), splice()는 함수 명도 비슷해서 많이 헷갈릴 수 있다고 생각합니다. 

 

우선 두 함수의 사전적인 의미와 꼼수 암기법을 사용해서 기억해 두시면 익숙해지기 전까지 유용하게 기억할 수 있을 것 같습니다.

사전적인 의미
slice: 썰다, 베다
splice: 잇다, 붙이다

꼼수 암기법
slice와는 다르게 splice ‘p(피)’가 있는데 피는 몸에서 생성되거나 출혈이 생기면 빠져나가기도 합니다. 즉 splice는 본체에 변형을 일으킨다!!

 

간단하게 복습할 겸 준비한 것이니 요약정리라 생각하시고 가볍게 봐주시면 감사하겠습니다. 

 

오늘 준비한 내용은 여기까지입니다. 

짧게 쓸려고 했는데 쓰다 보니 또 설명드리고 싶은 게 많아 길어졌네요 ㅜㅜ 


읽어주셔서 감사합니다 :)

좋아요 및 댓글 달아주시면 감사하겠습니다 :) 

궁금한 내용 및 잘못된 내용을 위한 댓글 혹은 토론하고 싶은 댓글은 백번, 만 번 환영입니다!!!

 

 

추가 수정

2023-11-01 / slice 주의 사항 내용 추가

2023-11-02 / 제목 변경

 
728x90