스프레드 문법 35

스프레드 문법의 대상은 이터러블이어야 한다.
스프레드 문법... 이 피연산자를 연산하여 값을 생성하는 연산자가 아니기에
스프레드 문법의 결과는 변수에 할당할 수 없다.
스프레드 문법의 결과물은 값으로 사용할 수 없고, 다음과 같이 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용할 수 있다.

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

함수의 인수로 사용하는 경우

// ES5  
function  foo(x,  y,  z)  {  
	console.log(x);  // 1  
	console.log(y);  // 2  
	console.log(z);  // 3  
}  
// 배열을 분해하여 배열의 각 요소를 파라미터에 전달하려고 한다.  
const  arr  =  [1,  2,  3];  
// apply 함수의 2번째 인수(배열)는 분해되어 함수 foo의 파라이터에 전달된다.  
foo.apply(null,  arr);  
// foo.call(null, 1, 2, 3);

// ES6  
function  foo(x,  y,  z)  {  
	console.log(x);  // 1  
	console.log(y);  // 2  
	console.log(z);  // 3  
}  
// 배열을 foo 함수의 인자로 전달하려고 한다.  
const  arr  =  [1,  2,  3];  
/* ...[1, 2, 3]는 [1, 2, 3]을 개별 요소로 분리한다(→ 1, 2, 3)  
spread 연산자에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다. */  
foo(...arr);

cf. Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받기 위해 매개변수 이름 앞에 ...을 붙인다.

배열에서 사용하는 경우

1. concat

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

// ES6  
const  arr  =  [1,  2,  3];  
// ...arr은 [1, 2, 3]을 개별 요소로 분리한다  
console.log([...arr,  4,  5,  6]);  // [ 1, 2, 3, 4, 5, 6 ]

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,  2,  3,  6];  
var  arr2  =  [4,  5];  
/*  apply 메소드의 2번째 인자는 배열. 이것은 개별 인자로 push 메소드에 전달된다.  
[3, 0].concat(arr2) → [3, 0, 4, 5]  
arr1.splice(3, 0, 4, 5) → arr1[3]부터 0개의 요소를 제거하고 그자리(arr1[3])에 새로운 요소(4, 5)를 추가한다.  */  
Array.prototype.splice.apply(arr1,  [3,  0].concat(arr2));  
console.log(arr1);  // [ 1, 2, 3, 4, 5, 6 ]

// ES6  
const  arr1  =  [1,  2,  3,  6];  
const  arr2  =  [4,  5];  
// ...arr2는 [4, 5]을 개별 요소로 분리한다  
arr1.splice(3,  0,  ...arr2);  // == arr1.splice(3, 0, 4, 5);  
console.log(arr1);  // [ 1, 2, 3, 4, 5, 6 ]

4. copy

ES5에서 기존 배열을 복사하기 위해서는 slice 메소드를 사용한다.
Spread 연산자를 사용하면 보다 간편하게 배열을 복사할 수 있다.

// ES5  
var  arr  =  [1,  2,  3];  
var  copy  =  arr.slice();  
console.log(copy);  // [ 1, 2, 3 ]  
// copy를 변경한다.  
copy.push(4);  
console.log(copy);  // [ 1, 2, 3, 4 ]  
// arr은 변경되지 않는다.  
console.log(arr);  // [ 1, 2, 3 ]

// ES6  
const  arr  =  [1,  2,  3];  
// ...arr은 [1, 2, 3]을 개별 요소로 분리한다  
const  copy  =  [...arr];  
console.log(copy);  // [ 1, 2, 3 ]  
// copy를 변경한다.  
copy.push(4);  
console.log(copy);  // [ 1, 2, 3, 4 ]  
// arr은 변경되지 않는다.  
console.log(arr);  // [ 1, 2, 3 ]

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

ES5에서 이터러블을 배열로 변환하려면 Function.prototype.apply 또는 Function.prototype.call 메서드를 사용하여 slice 메서드를 호출해야 한다.

//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((pre, cur) => pre + cur, 0);
}
console.log(sum(1,2,3)); // 6
//ES6 Rest 파라미터를 사용하는 방법
function sum(...args){
	return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1,2,3)); // 6

단, 이터러블이 아닌 유사 배열 객체는 스프레드 문법의 대상이 될 수 없다. 이터러블이 아닌 유사 배열 객체를 배열로 변경하려면 Array.from 메서드를 사용한다.

const  htmlCollection  =  document.getElementsByTagName('li');  
// 유사 배열인 HTMLCollection을 배열로 변환한다.  
const  newArray  =  [...htmlCollection];  // Spread 연산자  
// ES6의 Array.from 메소드를 사용할 수도 있다.  
// const newArray = Array.from(htmlCollection);

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

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}