본문 바로가기
> 프로그래밍 언어/Javascript

자바스크립트 배열의 slice()와 splice() 함수

by 자몽주스 2024. 9. 25.
728x90

자바스크립트 배열의 slice()와 splice() 함수 | 달레의 웹 프로그래밍 - YouTube

참고할 글

자바스크립트 배열의 slice()와 splice() 함수 | Engineering Blog by Dale Seo

 

자바스크립트 배열의 slice()와 splice() 함수

Engineering Blog by Dale Seo

www.daleseo.com


slice() 함수

어떤 배열의 특정 범위를 새로운 배열로 복사.

= 부분 배열 만들어 주는 함수.

 

첫 번째 인자 = 시작 인덱스

두 번째 인자 = 종료 인덱스.

 

시작 인덱스부터 종료 인덱스 까지의 값을 복사해서 반환한다.

배열 확인


nums.slice() 함수

5부터 9까지의 복사한 값을 갖고있는 새로운 배열 만들어보기.

= nums.slice() 함수 사용

2 개의 인자(파라미터)를 받는거 확인.

시작하는 인덱스와 종료하는 인덱스

시작하는 인덱스 5

종료하는 인덱스 10 입력

실행 해보면 5부터 9까지 나온거 확인할 수 있다.

= 부분배열 (원래 배열에서 얻어온 것)

 

주의할 점

첫번째 인자로 넘어오는 인덱스는

결과값에 포함이 되지만,

두 번째 인자로 넘어오는 종료 인덱스는

결과 값에 포함이 되지 않음

( 즉, 원하는 값의 +1 이다. 원하는 값이 9인데 +1)


slice() 함수
두 번째 인자 생략하기

이렇게 slice 함수 호출할 때 

10 만 넘겨 본 경우,

그러면 10부터 배열의 마지막 까지 얻을 수 있는 걸 확인. 

(인덱스면 하나씩 밀릴 텐데 인자 그대로 얻어짐 )


첫 번째 인자도 넘기지 않는 방법 

그냥 아무 인자도 안넘긴 경우

원래 배열이 그대로 복사된 걸 확인할 수 있다. 

즉, slice 함수에 아무 인자도 넘기지 않으면 

배열의 첫 번째 값 부터 마지막 값 까지

전체적으로 복제를 함.

 

첫 번째 인자만 넘기면

해당하는 인자의 인덱스부터 배열의 마지막 끝까지 복사하는 효과

 

두 개의 인자를 넘기면

범위에 해당하는 부분배열을 반환


slice 함수와 splice 함수

slice 함수는 splice 함수와 달리

아무리 많이 호출을 해도,

원본 배열의 값은 절대 건드리지 않음.

예를 들어서 nums 를 다시 출력해 본 경우,

맨 처음에 만들었던 nums 의 모양과 

완전히 동일한 걸 확인.

= 원본 배열이 그대로 보존돼야 하는 상황에서는 

slice함수 유용하게 사용 가능.


splice 함수()

 

배열로부터 특정 범위를 삭제하거나,

새로운 값을 추가하거나,

기존값 대체 가능

 

첫 번째 인자 = 시작 인덱스

두 번째 인자 = 몇 개의 값을 삭제할 지,

세 번째 인자 = 추가할 값을 가변인자로 넘길 수 있음

 

그리고 항상 삭제한 값을 갖고있는 배열을 반환한다.

아까와 동일하게 nums 라는 숫자 배열을 생성해놓고 알아보기.


 

5,6,7 이렇게 3개의 값 삭제해보기

 

 

우선 시작 인덱스를 넘기구,

몇 개를 지울 지 

deleteCount 로 두 번째 인자에 쓰는거 확인 가능.

3개 지울 거니까 3 써줌.

호출을 해보면 이렇게 5,6,7 나오는 거 확인할 수 있다.

여기서 원본배열 출력해보기

그러면 삭제된 거 확인할 수 있다. 


-5,-6,-7 을 추가해보기

똑같이 인덱스 5 를 첫 번째 인자로 넘김.

그리고 아무것도 삭제하지 않을 거니까

delete Count , 즉

2번 째 인자로 0 을 넘김.

그리고 가변인자로 추가할 값을 넘길 수 있음.

이렇게 - 붙인 숫자를 써주고

호출을 해주면

아무것도 호출이 되지 않는다. 

= 아무것도 지우지 않았기 때문.

그냥 저렇게 추가한 값 만 있음.

추가한 값 : -5, -6, -7

 

※splice 함수는 추가한 값을 반환하지 않음.

= 항상 삭제된 값을 반환함.

추가된 거 확인하는 방법:

원본 배열 출력.


값을 삭제하면서 추가해보기
= 값을 대체해보기.

인덱스 10이 가리키는 값 부터, 두개의 값

즉 , -10, -11 로 대체해 보기. 

인덱스 10 부터 먼저 써줌.

두 번째 인자에다가 2개의 값 삭제할 거니까 2 를 써준다.

그리고 뒤에는 추가할 것 써줌. 

= 대체할 값.

출력해본 결과

= 역시나 원본배열에서 삭제한 거만 뜸.

다시 nums 출력

-10, -11 로 바뀐거 확인.


splice 함수도 첫 번째 인자만 넘길 수 있다.

인덱스 15 부터 모든 값 삭제해보기

그럼 그 뒤에가 삭제됐다고 반환이 됨.

 

nums 출력했을 경우

= 15 이후로 값 사라진 거 확인.


splice() 주의할 점 

= 원본 배열도 변경이 된다.

= 의도치 않은 데이터 유실 가능성 있음.


slice() , splice() 비교하기

 

아까와 똑같이 배열 생성해보기


5 부터 7 까지 복사한 값을 담고있는
새로운 배열 얻고싶다면? 

1) slice 사용

인덱스 5 와 인덱스 8(종료인덱스)을 넘김.

2) splice 사용

첫 번째 인자로 마찬가지로 5를 넣고

두 번째 인자로는 몇 개를 삭제할 지 넘김. 

3 을 써준다. 

이것 또한 동일하게 5,6,7 넘김.


반복 호출했을 경우
1) slice 함수를 3번 호출함. 


= 항상 5,6,7 이 얻어진다. 

2) splice 함수를 3번 호출함. 

다른 출력값이 나오는 거 확인.

 

이런 현상이 생기는 이유 

우선 nums 를 출력해보면

splice 함수를 3번 호출해갖고, 

9개 숫자가 사라지고

11개만 남은걸 확인할 수 있다.

 

즉, 같은 배열을 반환하는 slice 함수와 달리

splice 함수는 계속해서 원본 배열을 깎아 먹기 때문에

여러번 호출을 할 수록 매번 다른 배열이 반환됨.

 

 

 

 


 

배열 생성 예시 확인하기
Array(20).fill().map((_, i) => i)

0부터 19까지의 숫자를 담은 배열을 만들고 있어요. 하나씩 뜯어볼게요!

  • Array(20): 길이가 20인 빈 배열을 만들어요.
  • 이 배열에는 값이 아직 채워져 있지 않아요.
    • 결과: [empty × 20]
  • .fill(): 이 빈 배열을 fill()로 채워요. fill() 메서드에 인자를 넣지 않으면,
  • 배열의 모든 값이 undefined로 채워져요.
    • 결과: [undefined, undefined, ..., undefined] (20개의 undefined)

.map((_, i) => i):

이 undefined로 채워진 배열을 map()으로 순회하며 새로운 배열을 만들어요.

  • map()은 배열의 각 요소를 변환해 새 배열을 반환하는 메서드예요.
    • 첫 번째 매개변수 _는 각 요소를 나타내는데,
    • 이번 경우에는 undefined라서 실제로는 사용하지 않아요.
    • 대신, 두 번째 매개변수 i는 현재 요소의 인덱스를 나타내요.
    • 인덱스 i가 새 배열의 값이 되어요.

결과적으로, [0, 1, 2, ..., 19] 배열이 만들어지는 거예요!

Array.fill()과 Array.from() 의 차이 알아보기 
Array.from({ length: 5 }, (_, i) => i + 1)

1. Array.fill()

  • 어떻게 동작하냐면?
    • 이미 존재하는 배열을 특정 값으로 채워 넣는 역할을 해요.
    • 보통 빈 배열을 먼저 만든 다음에 fill()로 채우는 방식으로 사용해요.
  • 특징
    • 항상 배열을 고정된 값으로 채워요.
    • 그 값을 map()이나 다른 방법으로 변형할 수는 있지만,
    • 기본적으로는 특정 값으로 채우는 게 목적이에요.
  • 예시:
const nums = Array(5).fill(0);
console.log(nums); // [0, 0, 0, 0, 0]
  • 설명:
    • 여기선 길이 5인 배열을 만든 후, 모든 요소를 0으로 채워 넣었어요.
    • 이후에 map()으로 변환하거나 가공할 수 있지만, 기본적으로는 채우는(fill) 용도.

2. Array.from()

  • 어떻게 동작하냐면?
    • 어떤 유사 배열 객체반복 가능한 객체에서 새로운 배열을 만들어 내요.

객체가 없더라도 { length: n } 같은 형식으로

임의의 길이를 설정하고 배열을 만들 수 있어요.

  • 특징
    • 배열을 유연하게 만들 수 있고,
    • 두 번째 인자로 즉시 변환도 가능해요.
    • from() 안에서 map() 같은 변환을 함께 처리할 수 있어요.
  • 예시:
const nums = Array.from({ length: 5 }, (_, i) => i + 1);
console.log(nums); // [1, 2, 3, 4, 5]
  • 설명:
    • 여기선 { length: 5 }로 길이 5인 배열을 만들고,
    • 두 번째 인자로 변환 로직을 넣어서 각 요소에 i + 1을 적용했어요.
    • 이렇게 동시에 배열을 만들고 변환하는 작업이 한 번에 가능해요.

차이점 정리

비슷한 점

둘 다 배열을 생성하고,

이후에 map() 등을 사용해 변환할 수 있다는 점에서는 비슷하지만,

Array.from()즉시 변환이 가능하고 더 유연해요.

이해하기 쉽게 비교하면:

  • Array.fill(): "이 빈 상자(배열)를 특정 값으로 꽉 채울게!"
  • Array.from(): "내가 원하는 길이규칙에 따라 바로 상자(배열)를 만들어줄게!"

따라서 상황에 따라 고정된 값으로 채워야 할 때 Array.fill(),

유연하게 배열을 만들고 변환할 때 Array.from()을 사용하면 좋아요!

 

Array(20).fill().map((_, i) => i)는 **map()**을 따로 사용한 반면,
Array.from({ length: 5 }, (_, i) => i + 1)은 Array.from()에서 바로 변환을 해준 이유

map()의 역할

map()은 배열의 각 요소를 변환해서 새로운 배열을 반환하는 메서드야.

즉, 배열의 모든 요소를 바꿀 쓰는 거야.

  • 언제 사용하냐면?
    • 이미 있는 배열을 다른 형식으로 바꾸고 싶을 때 사용해.
    • 예를 들어, 배열이 만들어진 다음에 그 배열의 각 요소를 변환해야 하는 경우.

Array.from()과 map()의 관계

  • Array.from()에서 변환하는 경우:

Array.from()은 배열을 만들면서 동시에 변환할 수 있어서

따로 map()을 붙일 필요가 없어.

    • 배열을 만들 때 동시에 변환할 수 있는 게 특징이야.
  • Array.fill()과 map()을 함께 쓰는 경우:
    • 반대로 Array.fill()은 단순히 배열을 고정된 값으로 채우기 때문에,
    • 그걸 다시 **변환하려면 map()**을 따로 써야 해.

Array.from()에도 map()을 붙일 수 있어?

네, Array.from()을 사용한 후에도 map()을 추가로 사용할 수 있어!

예를 들어, 배열을 한 번 만들고 나서 다시 변환할 필요가 있다면 그렇게 할 수 있어.

예시:

const nums = Array.from({ length: 5 }, (_, i) => i + 1).map(num => num * 2);
console.log(nums); // [2, 4, 6, 8, 10]
  • 설명: Array.from()으로 먼저 [1, 2, 3, 4, 5] 배열을 만들고,
  • 그 다음에 map()으로 각 숫자를 두 배로 변환했어.
  • 이처럼 Array.from()에서 배열을 만들고,
  • 그 배열을 또 변형해야 할 때 map()을 사용할 수 있어.

언제 map()을 붙이냐고?

배열을 변환해야 할 때 사용하는 거야.

만약 Array.from()을 쓸 때 변환이 충분하지 않거나,

추가적인 변환이 필요하다면 그때 map()을 붙여!

 

또는 이미 있는 배열에 대해 변형을 할 때도 map()을 써.

비교해서 보면:

  • Array.from()에서 바로 변환할 수 있는 경우:
const nums = Array.from({ length: 5 }, (_, i) => i + 1);
console.log(nums); // [1, 2, 3, 4, 5]

 

설명:

이 경우, 배열을 만들면서 이미 변환을 다 했어.

map()이 필요 없어.

  • 추가 변환이 필요한 경우 map()을 붙임:
const nums = Array(5).fill(0).map((_, i) => i + 1).map(num => num * 2);
console.log(nums); // [2, 4, 6, 8, 10]

 

설명:

fill()로 배열을 만들고, map()으로 [1, 2, 3, 4, 5]를 만든 다음,

다시 map()으로 그걸 변환했어.

결론

Array.from()은 배열을 만들 때 바로 변환이 가능하기 때문에,

필요하면 한 번에 끝낼 수 있어.

 

하지만 더 복잡한 변환이 필요하면 map()을 추가로 붙여서 변환할 수 있어.

 

언제 map()을 붙이냐면, 추가적인 변환이 필요할 때!

예를 들어, 배열을 만들 때 변환이 충분하지 않거나,

더 변형해야 할 때 사용하면 돼.

Array.from({ length: 5 }, map(_, i) => i + 1)
이렇게 비교해서 Array.from 은 바로 옆에 map 을 붙일 수 없는 건지

 

Array.from()과 map()을 바로 옆에 붙이는 것은 불가능해.

그 이유를 이해하기 쉽게 설명해볼게.

1. Array(20).fill().map()의 구조

  • Array(20).fill()로 먼저 배열을 만든 다음,
  • 그 배열에 대해 **map()**을 따로 적용하는 방식이야.
  • 즉, 배열을 만든 후에 map()을 사용하는 것이야.

2. Array.from()의 특징

  • Array.from()은 배열을 만들면서
  • 바로 두 번째 인자로 변환 함수를 받을 수 있어.

즉, Array.from() 안에서 이미 변환 로직이 처리되기 때문에

별도로 map()을 붙일 필요가 없는 것이지.

Array.from({ length: 5 }, (_, i) => i + 1);

위 코드에서 이미 (_, i) => i + 1이 map()처럼 동작하고 있어.

그래서 추가로 map()을 붙일 이유가 없고, 사실 붙일 수도 없어.

3. 왜 Array.from()은 map()을 바로 옆에 붙일 수 없을까?

Array.from()은 자체적으로 배열을 생성하는 동시에 변환하는 기능을 가지고 있어.

그러니까 이미 변환 로직을 내부적으로 처리하는 거야.

따라서 배열을 생성하면서

바로 두 번째 인자로 변환 함수를 받고 그걸로 작업을 마무리해버려.

  • 결과: Array.from()에서 배열을 만든 후, map()을 추가로 붙일 수는 있지만,
Array.from({ length: 5 }).map((_, i) => i + 1); // 가능

이런 식으로 사용하는 거지,

Array.from({ length: 5 }, map(...))처럼

바로 옆에 map()을 붙이는 건 문법적으로 불가능해.

 

이유는 Array.from()의 두 번째 인자가 이미 배열을 변환하는 역할을 하기 때문에

별도의 map() 함수는 받지 않는 거야.

결론

  • Array(20).fill().map(): 배열을 만들고 그 후에 map()으로 변환하는 구조.
  • Array.from(): 배열을 만들면서 바로 변환을 처리하므로 따로 map()을 옆에 붙이지 않음.

Array.from()은 내부적으로 변환을 처리하기 때문에 map()을 추가할 필요가 없고,

만약 추가 변환이 필요하면 배열을 만든 후에 map()을 사용해줘야 해.


 

728x90