logo태영이의 공부방

[JavaScript] 스프레드 문법

2023년 05월 12일

스프레드 문법

ES6에서 도입된 스프레드 문법(전개 분법) ...은 하나로 뭉쳐 있는 여러 값들의 집합을 펼쳐서 개별적인 값들의 목록으로 만든다.

  • 스프레드 문법을 사용할 수 있는 대상: for...of 문으로 순회할 수 있는 이터러블
    • Array
    • String
    • Map
    • Set
    • DOM 컬렉션(NodeList, HTMLCollection)
    • arguments
    • ...
console.log(...[1, 2, 3]); // 1 2 3

주의

스프레드 문법 ...은 피연산자를 연산하여 값을 생성하는 연산자가 아니므로 스프레드 문법의 결과는 변수에 할당할 수 없다. 즉, 스프레드 문법의 결과물은 값으로 사용할 수 없고 아래와 같이 쉼표로 구분한 값의 목록을 사용하는 문백에서만 사용할 수 있다.

  • 함수 호출문의 인수 목록
  • 배열 리터럴의 요소 목록
  • 객체 리터럴의 프로퍼티 목록

함수 호출문의 인수 목록에서 사용하는 경우

const arr = [1, 2, 3];
 
// 스프레드 문법 제공 이전
// apply: 2번째 인수는 apply 함수가 호출하는 함수의 인수 목록, 따라서 배열이 펼쳐 전달되는 효과가 있다.
const maxOld = Math.max.apply(null, arr); // 3
 
// Math.max: 여러 개의 숫자를 인수로 전달받아 인수 중에서 최대값을 반환
// 숫자가 아닌 배열을 인수로 전달할 경우 최대값을 구하지 못해 NaN 반환
// 배열을 스프레드 문법을 사용해 펼쳐서 전달
const max = Math.max(...arr); // 3

배열 리터럴 내부에서 사용하는 경우

  • concat
    • ES5에서 2개의 배열을 1개의 배열로 결합하고 싶은 경우 사용
      const arrOld = [1, 2].concat([3, 4]); // [1, 2, 3, 4]
    • 스프레드 문법
      const arr = [...[1, 2], ...[3, 4]]; // [1, 2, 3, 4]
  • splice
    • ES5에서 배열의 중간에 다른 배열의 요소들을 추가하거나 제거하고 싶은 경우 사용
      let a1 = [1, 2];
      let a2 = [3, 4];
       
      // [1, 0].concat(a2): [1, 0, 3, 4]로 평가
      // a1[1]부터 0개의 요소를 제거하고 그 자리에 새로운 요소를 삽입
      Array.prototype.splice.apply(a1, [1, 0].concat(a2));
      console.log(a1) // [1, 3, 4, 2]
    • 스프레드 문법
      let a1 = [1, 2];
      let a2 = [3, 4];
       
      a1.splice(1, 0, ...a2);
      console.log(a1)
  • 배열 복사
    • ES5에서 배열을 복사하고 싶은 경우 사용
      const ori = [1, 2];
      const copy = ori.slice();
    • 스프레드 문법
      const ori = [1, 2];
      const copy = [...ori];
  • 이터러블을 배열로 변환
    • ES5에서 이터러블을 배열로 변환하려면 Function.prototype.apply 또는 Function.prototype.call 메서드를 사용하여 slice 메서드를 호출해야 함
      function print() {
        const args = Array.prototype.slice.call(arguments);
        console.log(args);
      }
       
      print(1, 2); // [1, 2]
    • 스프레드 문법
      function print() {
        console.log([...arguments]);
      }
       
      print(1, 2); // [1, 2]
    • Rest 파라미터
      const print = (...args) => console.log(args);
      print(1, 2); // [1, 2]

객체 리터럴 내부에서 사용하는 경우

TC39 프로세스의 stage4 단계에 제안되어 있는 스프레드 프로퍼티를 사용하면 객체 리터럴의 프로퍼티 목록에서도 스프레드 문법을 사용할 수 있다. 스프레드 프로퍼티 제안은 일반 객체를 대상으로도 스프레드 문법의 사용을 허용한다. 스프레드 프로퍼티는 Object.assign 메서드를 대체할 수 있는 문법이다.

// 객체 복사(얕은 복사)
const ori = { a: 1, b: 2 };
const copy = { ...obj };
 
// 객체 병합
const merged = { a: 1, b: 2, ...{ c: 3, d: 4} };