자바스크립트 배열의 slice()와 splice() 함수 | 달레의 웹 프로그래밍 - YouTube
참고할 글
자바스크립트 배열의 slice()와 splice() 함수 | Engineering Blog by Dale Seo
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()을 사용해줘야 해.
'> 프로그래밍 언어 > Javascript' 카테고리의 다른 글
[코딩애플] 진짜 웹개발로 배우는 실용 자바스크립트 6강 (0) | 2023.09.23 |
---|---|
[코딩애플] 진짜 웹개발로 배우는 실용 자바스크립트 5강 (0) | 2023.09.23 |
[코딩애플] 진짜 웹개발로 배우는 실용 자바스크립트 4강 (0) | 2023.09.17 |
[코딩애플] 진짜 웹개발로 배우는 실용 자바스크립트 3강 (0) | 2023.09.17 |
[코딩애플] 진짜 웹개발로 배우는 실용 자바스크립트 1강 ~ 2강 (2) | 2023.09.17 |