스프레드 문법 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}