slice, splice 비교 분석

rada·2025년 3월 27일
0

개발

목록 보기
18/43

해당 페이지에는 Array.prototype의 slice, splice에 대해서만 다룬다.

🚒 JS Data Type

내장 객체를 사용하려면 기본적으로 데이터 타입을 알아두어야 하고, 그래야 이해가 더 쉽다.

  • 원시 값(Primitive values - Immutable)
    - undefined, null, Boolean, Number, BigInt, String, Symbol
  • 참조형(Reference Type - mutable Value)
    - Object(배열,함수,객체)
Type typeof return value Object wrapper
Null 타입 "object" N/A
Undefined 타입 "undefined" N/A
Boolean 타입 "boolean" Boolean
Number 타입 "number" Number
BigInt 타입 "bigint" BigInt
String 타입 "string" String
Symbol 타입 "symbol" Symbol

🚒 Array.prototype.slice()

slice() 메서드는 최대 2개의 인수(start, end)만 받습니다.
3개 이상의 인수를 전달하면 무시하고, 첫 두 개의 인수(start, end)만 사용합니다.

특징: 얕은 복사 (Shallow Copy)

  • 원본 배열을 변경하지 않고 새 배열을 반환합니다.
  • 1차원 배열에서는 완전히 독립된 복사본이 생성됩니다.
  • 중첩된 객체/배열이 있을 경우 참조만 복사하므로, 원본과 복사본이 공유됩니다.
const original = [1, 2, [3, 4], { a: 5 }];
const copied = original.slice();

copied[0] = 100; // 원시값은 독립적 (원본 영향 X)
copied[2][0] = 99; // 중첩 배열은 참조 공유 (원본도 변경됨)

console.log(original); 
// [1, 2, [99, 4], { a: 5 }] (중첩 구조만 변경됨)

🏠 Array.prototype.slice()의 문법

arr.slice([start[, end]])
  • start (옵션): 추출 시작 인덱스 (기본값: 0)
  • end (옵션): 추출 종료 인덱스 (기본값: 배열 길이)
  • 반환값: start부터 end-1까지의 새 배열 (얕은 복사)

🛟 slice(start, end) 기본 동작 👀

  • start: 추출을 시작할 인덱스 (포함)
  • end: 추출을 종료할 인덱스 (미포함, 생략 시 배열 끝까지)
  • 원본 배열은 변경되지 않음 (비파괴적 메서드)
  • 얕은 복사(Shallow Copy) 수행 → 중첩된 객체/배열은 참조가 복사됩니다.

🏠 slice(1,4,5,6)의 실제 동작

const original = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const copied = original.slice(1, 4, 5, 6); // 3번째 인수(5)부터는 무시됨

console.log(copied); // [1, 2, 3] (인덱스 1~3까지 추출)

동작 순서:

  • 첫 번째 인수 1 → 시작 인덱스로 설정
  • 두 번째 인수 4 → 종료 인덱스로 설정
  • 5, 6 → 무시 (JavaScript 엔진이 에러 없이 처리)

🏠 왜 이런 결과가 나오나요?

JavaScript 함수는 정의된 매개변수보다 많은 인수를 받아도 에러가 발생하지 않습니다.
slice()는 2개의 매개변수만 사용하고, 나머지는 무시합니다.
만약 slice(1,4,5,6) 대신 splice(1,4,5,6)를 사용했다면 전혀 다른 결과가 나옵니다.

🏠 주의사항

  • 인수 개수: slice()는 2개 이상의 인수를 무시하지만, splice()는 추가 인수를 삽입할 값으로 처리합니다.
  • 음수 인덱스: slice(-3) → 뒤에서 3번째부터 추출 (유용한 기능!)
  • 얕은 복사: 중첩된 객체/배열은 참조가 복사됩니다.
const fruits = ["🍎", "🍌", "🍊", "🍓", "🥝"];

// (1) 기본 사용법
console.log(fruits.slice(1, 4)); // ["🍌", "🍊", "🍓"]
// (2) 인수 무시 사례
console.log(fruits.slice(1, 4, "🍒", "🍍")); // ["🍌", "🍊", "🍓"] (추가 인수 무시)
// (3) 음수 인덱스
console.log(fruits.slice(-3)); // ["🍊", "🍓", "🥝"] (뒤에서 3개)

🚘 결론

  • slice(1,4,5,6) → slice(1,4)와 동일하게 작동 (추가 인수 무시).
  • 원본 배열은 변경되지 않으며, 인덱스 1~3의 요소가 추출됩니다.
  • 중첩 구조가 있다면 얕은 복사됨을 주의하세요!
const original = [0, 1, 2, 3, 4, 5];
const copied = original.slice(1, 4, 99, 100);

console.log(copied); // [1, 2, 3] ✅
console.log(original); // [0, 1, 2, 3, 4, 5] (원본 유지) ✅

🚒 Array.prototype.splice()

Array.prototype.splice()는 JavaScript 배열에서 요소를 삭제, 추가 또는 교체하는 강력한 메서드입니다. 가장 핵심적인 배열 조작 메서드 중 하나로, 원본 배열을 직접 수정한다는 특징이 있습니다.

특징: 복사가 아닌 원본 조작

  • 원본 배열을 직접 수정합니다.
  • 깊은 복사도, 얕은 복사도 아닙니다. 단순히 원본에서 요소를 삭제/추가합니다.
  • 반환값은 삭제된 요소들의 배열이며, 이때 삭제된 요소들은 얕은 복사됩니다.
const original = [1, 2, [3, 4], { a: 5 }];
const removed = original.splice(1, 2); // 인덱스 1부터 2개 삭제

console.log(removed); // [2, [3, 4]] (얕은 복사된 삭제 요소)
console.log(original); // [1, { a: 5 }] (원본이 변경됨)

removed[1][0] = 99; // 삭제된 배열의 참조는 유지
console.log(original); // [1, { a: 5 }] (원본엔 영향 없음)

🏠 Array.prototype.splice() 문법

array.splice(start[, deleteCount[, item1[, item2[, ...]]])
  • start: 변경을 시작할 인덱스 (음수일 경우 배열 끝에서부터 계산)
  • deleteCount (옵션): 제거할 요소의 수 (0이면 아무것도 삭제 안 함)
  • item1, item2, ... (옵션): 추가할 요소들
  • 반환값: 삭제된 요소들로 이루어진 새 배열 (삭제 안 하면 빈 배열)

🛟 주요 기능 3가지

(1) 요소 삭제

const arr = ['A', 'B', 'C', 'D'];
const removed = arr.splice(1, 2); // 인덱스 1부터 2개 삭제

console.log(arr);    // ['A', 'D'] (원본 변경)
console.log(removed); // ['B', 'C'] (삭제된 요소)

(2) 요소 추가

const arr = [1, 2, 5];
arr.splice(2, 0, 3, 4); // 인덱스 2에서 0개 삭제 후 3, 4 추가

console.log(arr); // [1, 2, 3, 4, 5]

(3) 요소 교체

const arr = ['🍎', '🍌', '🍊'];
arr.splice(1, 1, '🍓', '🥝'); // 인덱스 1에서 1개 삭제 후 2개 추가

console.log(arr); // ['🍎', '🍓', '🥝', '🍊']

🏠 특수한 사용법

(1) 음수 인덱스

const arr = [1, 2, 3, 4];
arr.splice(-2, 1); // 뒤에서 2번째부터 1개 삭제

console.log(arr); // [1, 2, 4]

(2) 전체 삭제

const arr = [1, 2, 3];
arr.splice(0); // 인덱스 0부터 모두 삭제

console.log(arr); // []

(3) 중간에 배열 삽입

const arr = [1, 5];
arr.splice(1, 0, ...[2, 3, 4]); // 스프레드 연산자 활용

console.log(arr); // [1, 2, 3, 4, 5]

🏠 주의사항

중첩 객체 참조:

const arr = [{a: 1}, {b: 2}];
const removed = arr.splice(0, 1);
removed[0].a = 99; // 원본 객체도 변경됨!
console.log(arr[0]); // {a: 99} (참조 유지)

deleteCount 생략 시:

const arr = [1, 2, 3];
arr.splice(1); // start부터 끝까지 모두 삭제
console.log(arr); // [1]

🏠 실제 활용 예제

// (1) 특정 요소 제거
function removeItem(arr, item) {
  const index = arr.indexOf(item);
  if (index !== -1) arr.splice(index, 1);
  return arr;
}

// (2) 배열 중간에 여러 요소 삽입
const numbers = [1, 100];
numbers.splice(1, 0, ...[2, 3, 4]); // [1, 2, 3, 4, 100]

Array.prototype.splice()는 원본 배열을 직접 조작해야 할 때 매우 유용하지만, 불변성이 중요한 경우(React 상태 관리 등)에는 slice() + 스프레드 연산자를 조합하는 것이 더 안전합니다.

🪧 slice vs splice 비교

// (1) slice() - 원본 변경 없음(얕은 복사)
const arr1 = [0, 1, 2, 3, 4];
const result1 = arr1.slice(1, 4, 99); // [1, 2, 3] (99 무시)
console.log(arr1); // [0, 1, 2, 3, 4] (원본 유지)

// (2) splice() - 원본 변경(복사가 아닌 원본 조작)
const arr2 = [0, 1, 2, 3, 4];
const result2 = arr2.splice(1, 4, 5, 6); // [1, 2, 3, 4] (삭제된 요소)
console.log(arr2); // [0, 5, 6] (원본이 변경됨)
메서드slice(start, end)splice(start, deleteCount, ...items)
원본 변경❌ (원본 유지)⭕ (원본을 직접 수정)
반환값추출된 새 배열삭제된 요소 배열
용도배열 일부 복사배열 요소 삭제/추가
사용 목적삭제/추가/교체데이터 추출
성능빠름 (원본 조작)느림 (새 배열 생성)
profile
So that my future self will not be ashamed of myself.

0개의 댓글