2 minute read

스프레드 문법

일명 전개문법이라 불리는 스프레드 문법(Spread syntax)은 하나로 뭉쳐있는 여러 값들의 집합을 펼쳐서 개별적인 값들의 목록으로 만든다. ...을 대상 앞에 붙여 사용하며, 사용 가능한 대상은 Array, String, Map, Set, DOM 컬렉션(NodeList, HTMLCollection), arguments와 같이 for … of문으로 순회할 수 있는 이터러블에 한정된다.

스프레드 문법의 결과는 값이 아니다. 즉 스프레드 문법 …이 피연산자를 연산해 값을 생성하는 연산자가 아니라는 말이다. 따라서 스프레드 문법의 결과는 변수에 할당할 수 없다.

const list = ...[1,2,3]; // SyntaxError: unexpected token ...

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

요소들의 집합체인 배열을 펼쳐서 개별적인 값들의 목록으로 만든 후 이를 함수의 인수 목록을 전달해야 하는 경우가 있다.

const arr = [1,2,3]

const max = Math.max(arr); // NaN
// Math.max 메서드에서 숫자가 아닌 배열을 인수로 전달하면 최대값을 할 수 없으므로 NaN을 반환한다.

const newMax = Math.max(...arr) // 3
// 스프레드 문법을 사용하면 배열 arr값을 펼쳐서 1,2,3으로 받고 이 중 최대값인 3을 반환한다.

const anotherNewMax = Math.max.apply(null, arr); // 3
// 스프레드 문법이 제공되기 이전에는 apply 메서드를 사용했다. (알아둘 필요는 없을듯?)

⚡️ 주의할 점

Rest 파라미터와 형태가 동일하니 혼동하지 않도록 주의하자.

  • Spread 문법은 이터러블을 펼쳐서 개별적인 값들의 목록을 만드는 것.
  • Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받기 위한 것 (얘는 매개변수 앞에 ...을 붙여서 사용)
function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

sum(1,2,3) // 6
sum(1,2,3,4) // 10

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

스프레드 문법을 사용하면 더 간결하고 가독성 좋게 표현할 수 있다.

  • concat
const arr = [1,2].concat([3,4]);
console.log(arr); // [1, 2, 3, 4]
// concat을 사용해도 좋지만 더 간결하게 스프레드 문법을 사용해보자
const arr2 = [...[1, 2], ...[3, 4]];
console.log(arr2); // [1, 2, 3, 4]
  • splice
// splice는 어떤 배열 중간에 다른 배열의 요소들을 추가하거나 제거할 때 사용하는 메서드이다.

const arr1 = [1, 4];
const arr2 = [2, 3];

arr.splice(1, 0, arr2); // 기대한 결과가 [1, 2, 3, 4]였으나 실제는 다르다/
console.log(arr1);  // [1, [2, 3], 4]

이를 스프레드 문법을 사용하면 간단해진다.
arr.splice(1, 0, ...arr2);				// 위 splice에서 원본 배열이 바뀐건 생략했지만 항상 명심하자
console.log(arr1); [1, 2, 3, 4]   // splice는 원본 배열을 직접 변경하는 메서드다.
  • slice
const origin = [1, 2];
const copy = origin.slice();

console.log(copy); // [1, 2]
console.log(copy === origin); // false

// 스프레드 문법을 사용하면 더 간결하고 가독성 좋게 표현 가능하다.
const origin2 = [1, 2];
const copy2 = [...origin];

console.log(copy2); // [1, 2]
console.log(copy2 === origin2); // false
  • 이터러블을 배열로 변환
function sum() {
  var args = Array.prototype.slice.call(arguments);

  return args.reduce(function (pre, cur) {
    return pre + cur;
  }, 0);
}
console.log(sum(1, 2, 3)); // 6

// 스프레드 문법을 사용하면 더 간결해진다.
function sum() {
  return [...arguments].reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3)); // 6

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

const obj = { x: 1, y: 2 };
const copy = { ...obj };   // 스프레드 프로퍼티
console.log(copy); // { x: 1, y: 2 }
console.log(obj === copy); // false (얕은 복사)

// 객체 병합
const merged = { x: 1, y: 2, ...{ a: 3, b: 4 } };
console.log(merged); // { x: 1, y: 2, a: 3, b: 4 }
const merged2 = { ...{ x: 1, y: 2 }, ...{ y: 10, z: 3 } };
console.log(merged2); // { x: 1, y: 10, z: 3 }

참고 자료

모던 자바스크립트 Deep Dive

Rest 파라미터 mdn 문서