ES6에서 도입된 스프레드문법 ( ... ) 은 하나로 뭉쳐있는 여러 값들의 집합을 펼쳐서(spread) 개별적인 값들의 목록으로 만든다.
스프레드문법을 사용할 수 있는 대상은 순회할 수 있는 이터러블에 한정된다.
Array, String, Map, Set, arguments 등 --> ( 객체는 안됨. 순서가 없으므로 )
첫번째 인자값에 첫번째 요소가, 두번째 인자값에 두번째 요소가 자동으로
console.log(...[1,2,3]); 1 2 3
console.log(...'hello'); h e l l o
스프레드문법의 결과는 값이 아니라 값들의 목록이다.
따라서 변수에 할당할 수 없다.
var result = ...[1,2,3]; // SyntaxError
그렇다면 언제 사용할 수 있을까?
다음과 같이 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용 할 수 있다.
앞서 공부했던 Math.max
는 가장 큰 수를 뽑아내는 메서드이다.
스프레드문법은 값이 아니라 값들의 목록이기 때문에 그냥 ...arr 를 쓰면 에러가 발생한다.
이 같은 문제를 해결하기 위해 배열을 펼쳐서 요소들을 개별적인 값들의 목록으로 만든 후 Math.max
의 인수로 전달해야한다.
const arr = [1,2,3];
Math.max(1,2); // 2
console.log(...arr) // SyntaxError
console.log(Math.max(...arr)); // 3 <-- 배열은 이렇게 써야함
스프레드 문법은 Rest 파라미터와 형태가 동일하여 혼동할 수 있으므로 주의할 필요가 있다.
Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받기 위해 매개변수 이름 앞에 ... 을 붙이는 것이다.
스프레드 문법은 여러개의 값이 하나로 뭉쳐있는 배열과같은 이터러블을 펼쳐서 개별적인 값들의 목록을 만드는 것이다.
따라서 두 개의 개념은 서로 반대의 개념이다.
ES5에서 2개의배열을 1개로 합치고 싶을 때 concat
메서드를 사용해야 했다.
하지만 스프레드 문법을 사용하면 별도의 메서드를 사용하지 않고도 합칠 수 있다.
var arr = [1,2].concat([3,4]);
console.log(arr); // [1,2,3,4]
const arr = [...[1,2], ...[3,4]];
console.log(arr); // [1,2,3,4]
ES5에서 어떤 배열에 다른 배열의 요소를 추가하거나 제거하려면 splice
메서드를 사용해야했다.
이러한 경우 문제점은 배열 자체가 추가되기 때문에 해체하고 넣어야한다.
var arr1 = [1,4];
var arr2 = [2,3];
arr1.splice(1,0,arr2);
console.log(arr1); // [1,[2,3],4]
스프레드 문법을 사용하면 간편하게 배열을 추가할 수 있다.
var arr1 = [1,4];
var arr2 = [2,3];
arr1.splice(1,0,...arr2);
console.log(arr1); // [1,2,3,4]
ES5에서 배열을 복사라혀면 slice
메서드를 사용해야 했다.
스프레드 문법을 사용하면 간편하게 배열을 추가할 수 있으며, 이 때 slice와 마찬가지로 원본배열을 얕은복사하여 새로운 복사본을 생성한다.
var arr = [1, 4];
// var copy = arr.slice();
var copy = [...origin];
console.log(arr); // [1,4]
스프레드 문법을 사용하면 간편하게 이터러블 배열로 변환할 수 있다.
arguments객체는 이터러블이면서 유사배열이다. 따라서 스프레드 문법의 대상이된다.
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 merge = {x:1, y:2, ... {a:3, b:4}};
console.log(merge); // {x:1, y:2, a:3, b:4}
스프레드 문법이 도입되기 전에는 Object.assign
메서드를 사용하여 여러개의 객체를 병합하거나 특정 프로퍼티를 변경 또는 추가했다.
// 객체 병합
// 프로퍼티가 중복되는 경우 뒤에 위치한게 덮어씌움
const marged = Object.assign({}, { x:1, y:2 }, { y:10, z:3 });
console.log(marged); // {x:1, y:10, z:3}
// 특정 프로퍼티 변경
const changed = Object.assign({}, { x:1, y:2 }, { y:100 });
console.log(changed); // {x:1, y:100}
// 프로퍼티 추가
const added = Object.assign({ x:1, y:2 }, { z:0 });
console.log(added); // {x:1, y:2, z:0}
스프레드 프로퍼티는 Object.assign
메서드를 대체할 수 있는 간편한 문법이다.
위에 있는 것을 스프레드 문법으로 바꿔보자
Object.assign
을 빼고 {}로 묶어 객체리터럴 앞에 ... 을 붙여주면 쉽게 바뀐다.
// 객체 병합
// 프로퍼티가 중복되는 경우 뒤에 위치한게 덮어씌움
const marged = {...{ x:1, y:2 }, ...{ y:10, z:3 }};
console.log(marged); // {x:1, y:10, z:3}
// 특정 프로퍼티 변경
const changed = {...{ x:1, y:2 }, ...{ y:100 }};
console.log(changed); // {x:1, y:100}
// 프로퍼티 추가
const added = {...{ x:1, y:2 }, ...{ z:0 }};
console.log(added); // {x:1, y:2, z:0}