스프레드문법

5o_hyun·2022년 2월 23일
0
post-thumbnail

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

그렇다면 언제 사용할 수 있을까?

다음과 같이 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용 할 수 있다.

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

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

앞서 공부했던 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 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받기 위해 매개변수 이름 앞에 ... 을 붙이는 것이다.
스프레드 문법은 여러개의 값이 하나로 뭉쳐있는 배열과같은 이터러블을 펼쳐서 개별적인 값들의 목록을 만드는 것이다.

따라서 두 개의 개념은 서로 반대의 개념이다.

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

1. concat

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]

2. splice

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]

3. 배열 복사

ES5에서 배열을 복사라혀면 slice메서드를 사용해야 했다.
스프레드 문법을 사용하면 간편하게 배열을 추가할 수 있으며, 이 때 slice와 마찬가지로 원본배열을 얕은복사하여 새로운 복사본을 생성한다.

var arr = [1, 4];
// var copy = arr.slice();
var copy = [...origin];

console.log(arr); // [1,4]

4. 이터러블 배열로 반환

스프레드 문법을 사용하면 간편하게 이터러블 배열로 변환할 수 있다.
arguments객체는 이터러블이면서 유사배열이다. 따라서 스프레드 문법의 대상이된다.

function sum() {
  return [...arguments].reduce((pre,cur) => pre + cur , 0);
}
console.log(sum(1,2,3)); // 6

// 더 자세히 공부 필요

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

스프레드문법의 대상은 이터러블이어야 하지만 스프레드 프로퍼티의 제안은 일반 객체를 대상으로도 스프레드 문법의 사용을 허용한다.

앞에서 리터럴에 ... 붙이는게 아니라, 변수명에 스프레드 연산자를 쓰는 경우에는 얕은 복사가 된다.

// 객체 복사(얕은 복사)
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}
profile
학생 점심 좀 차려

0개의 댓글