업데이트:

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

Array, String, Map, Set, DOM 컬렉션, arguments 와 같이 이터러블에 한정하여 스프레드 문법을 사용할 수 있다.

// 배열
console.log(...[1, 2, 3]); // 1 2 3
// 문자열
console.log(... 'Hello'); // H e l l o
// Map
console.log(...new Map([['a', '1'], ['b', '2']])); // ['a', '1'] ['b', '2']

위와 같이 …을 붙여 사용한다.

앞에서 배운 rest 파라미터와 헷갈릴 수 있는데 매개변수 앞에 …을 붙여서 사용하고 나머지 매개변수들을 의미하기 때문에 스프레드 문법과는 완전히 반대의 개념이다.

🔍 Rest 파라미터와 스프레드 문법의 차이

//rest 파라미터 : 함수에 전달된 인수들의 목록을 배열로 전달받음.
function foo(...rest){
	console.log(rest); // [1, 2, 3]
}

//스프레드 문법 : 이터러블을 펼쳐서 개별적인 값들의 목록을 만듬.
foo(...[1,2,3]); // 1 2 3  

스프레드 문법이 유용하게 쓰이는 경우들을 살펴보자 !

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

배열이나 이터러블을 함수의 인수로 전달할 때, 스프레드 문법이 제공되기 전에는 Function.prototype.apply를 사용했었다.

var arr = [1, 2, 3];
var max1 = Math.max(arr); // NaN
// 그냥 배열을 인수에 전달하면 최대값을 구할 수 없다.

// 배열이 펼쳐져서 인수로 전달되는 효과가 있다.
var max2 = Math.max.apply(null, arr); // 3

🎯 스프레드 문법 사용

const arr = [1, 2, 3];

const max = Math.max(...arr); // 1 2 3 

스프레드 문법을 사용하여 간결하고 가독성이 좋아졌다.

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

1) concat

// ES5
var arr = [1, 2].concat([3, 4]);
console.log(arr); // [1, 2, 3, 4]
// ES6
const arr = [...[1, 2], ...[3, 4]];
console.log(arr); // [1, 2, 3, 4]

문자열을 잇는 concat 메서드를 사용하지 않고도 2개의 배열을 1개의 배열로 결합할 수 있다.

2) push

// ES5
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];

// apply 메소드의 2번째 인자는 배열. 이것은 개별 인자로 push 메소드에 전달된다.
Array.prototype.push.apply(arr1, arr2);

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

// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// ...arr2는 [4, 5, 6]을 개별 요소로 분리한다
arr1.push(...arr2); // == arr1.push(4, 5, 6);

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

3) splice

배열 중간에 배열을 삽입할 때, 스프레드 문법을 이용하여 간단히 표현할 수 있다.

// ES5
var arr1 = [1, 4];
var arr2 = [2, 3];

Array.prototype.splice.apply(arr1, [1,0].concat(arr2));
console.log(arr1); // [1, 2, 3, 4]

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

arr1.splice(1,0, ...arr2); // 배열 arr1의 1번 인덱스에 0개를 제거하고 arr2배열을 추가한다.
console.log(arr1); // [1, 2, 3, 4]

4) 배열 얕은 복사

// ES5
var origin = [1, 2];
var copy = origin.slice();

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

// ES6
var origin = [1, 2];
var copy = [...origin];

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

slice 메서드와 스프레드 문법 둘 다 얕은 복사를 한다.

5) 이터러블을 배열로 변환

🥕 이터러블이면서 유사 배열 객체인 arguments

// ES5
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

// ES6 
// 스프레드 문법 사용
function sum() {
	return [...arguments].reduce(function((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3)); // 6

🥕 Rest 파라미터 사용

const sum = (..args) => args.reduce((pre, cur) => pre + cur, 0);
console.log(sum(1, 2, 3)); // 6

위 두가지 방법 중에서는 rest 파라미터를 사용하는 편이 더 좋다고 한다.

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

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

// 특정 프로퍼티 변경
const changed = { ...{ x: 1, y: 2 }, y: 100 };
// changed = { ...{ x: 1, y: 2 }, ...{ y: 100 } }
console.log(changed); // { x: 1, y: 100 }

// 프로퍼티 추가
const added = { ...{ x: 1, y: 2 }, z: 0 };
// added = { ...{ x: 1, y: 2 }, ...{ z: 0 } }
console.log(added); // { x: 1, y: 2, z: 0 }

객체를 병합할 때 프로퍼티가 중복되면 뒤에 위치한 프로퍼티가 우선권을 가진다.

댓글남기기