본문 바로가기

ECMAScript 6

Spread 연산자

Spread 연산자

Spread 연산자 ...는 연산자의 대상 배열 또는 이터러블을 개별 요소로 분리해주는 역할을 하는 연산자이다.

// ...[1, 2, 3]은 [1, 2, 3]을 개별 요소로 분리한다. ( -> 1, 2, 3 )
console.log(...[1, 2, 3]);

// 문지열은 이터러블이다.
console.log(...'Hello'); // H e l l o

// Map과 Set은 이터러블이다.
console.log(...new Map([['a', '1'], ['b', '2']])); // ['a', '1'], ['b', '2']
console.log(...new Set([1, 2, 3])); // 1 2 3

다음은 이 Spread 연산자를 사용하는 경우에 대해서 살펴보도록 하겠다.


#1 함수의 인자로 사용하는 경우

배열을 함수의 인자로 사용하고, 배열의 각 요소를 개별적인 파라미터로 전달하고 싶은 경우, ES5에서는 Function.prototype.apply를 사용하는 것이 일반적이다.
// ES5
function boo (x, y, z) {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}

// 배열을 boo 힘수의 전달하려고 한다
const arr = [1, 2, 3];

// apply 힘수의 2번째 인자(배열)는 호출하려는 함수(boo)의 개별 인자로 전달된다.
boo.apply(null, arr);

하지만 ES6에서는 Spread 연산자를 이용하여 만든 배열을 함수의 인수로 사용하게 되면 배열의 요소를 개별적으로 분리하여 순차적으로 파라미터에 할당한다.

// ES6
function boo (x, y, z) {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}

// 배열을 boo 함수의 인자로 전달하려고 한다.
const arr = [1, 2, 3];

/*
...[1, 2, 3]은 [1, 2, 3]을 개별 요소로 분리한다. ( -> 1, 2, 3 )
Spread 연산자에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다.
*/
boo(...arr);

전 포스팅에서 살펴본 Rest 파라미터는 Spread 연산자를 사용하여 파라미터를 정의한 것을 의미한다.

이는 형태가 동일하여 혼동할 가능성이 있으므로 주의가 필요하다.

/*
Spread 연산자를 사용한 매개변수 정의 (Rest 파라미터)
...rest는 분리된 요소들들 함수 내부의 배열로 전달한다.
*/
function boo(param, ...rest) {
console.log(param); // 1
console.log(rest); // [2, 3]
}
boo(1, 2, 3);

/*
Spread 연산자를 사용한 인수
배열 인수는 분리되어 순차적으로 매개변수에 할당
*/
function goo(x, y, z) {
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3
}

/*
...[1, 2, 3]은 [1, 2, 3]을 개별 요소로 분리한다. ( -> 1, 2, 3 )
Spread 연산자에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다.
*/
goo(...[1, 2, 3]);

또 Rest 파라미터는 반드시 마지막 파라미터여야 하지만 Spread 연산자를 사용한 인수는 자유롭게 사용할 수 있다.

// ES6
function boo(q, w, e, r, t) {
console.log(q); // 1
console.log(w); // 2
console.log(e); // 3
console.log(r); // 4
console.log(t); // 5
}

/*
...[2, 3]은 [2, 3]을 개별 요소로 분리한다. ( -> 2, 3 )
Spread 연산자에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다.
*/
boo(1, ...[2, 3], 4, ...[5]);


#2 배열에서 사용하는 경우

다음은 배열에서 사용하는 경우이다.

Spread 연산자를 배열에서 사용하면 보다 간결하고 가독성이 좋게 표현할 수 있다.

ES5에서 사용하던 방식과 비교하여 살펴보자.


#2-1 concat

ES5에서 기존 배열의 요소를 새로운 배열 요소의 일부로 만들고 싶ㄹ은 경우, 배열 리터럴만으로 해결이 불가능하고 concat 메소드를 사용해야 한다.
// ES5
var arr = [1, 2, 3];
console.log(arr.concat(4, 5, 6)); // [1, 2, 3, 4, 5, 6]

ES6에서 Spread 연산자를 사용하면 배열 리터럴 만으로 기존 배열의 요소를 새로운 배열 요소의 일부로 만들 수 있다.

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


#2-2 push

ES5에서 기존 배열에 다른 배열의 개별 요소를 각각 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]

이것을 Spread 연산자를 사용하면 아래와 같이 보다 간편하게 표현이 가능하다.

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

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


#2-3 splice

ES5에서 기존 배열에 다른 배열의 개별 요소를 삽입하려면 아래 예제와 같은 방법을 사용해야했다.
// ES5
var arr1 = [1, 2, 3, 6];

var arr2 = [4, 5];

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

ES6 Spread 연산자를 사용해보자.

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

// ...arr2는 [4, 5]를 개별 요소로 분리한다.
arr1.splice(3, 0, ...arr2); // arr.splice(3, 0, 4, 5); 와 같다.

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


#2-4 copy

ES5에서 기존 배열을 복사하려면 slice 메소드를 사용한다.
// 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 Spread 연산자를 사용해보자.

// ES6
const 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]

arr.slice();를 귀찮게 치지 않고 Spread 연산자로 보다 간단히 표현할 수 있다.


#3 객체에서 사용하는 경우

마지막으로 객체에서 Spread 연산자를 사용하는 경우이다.

Spread 연산자를 사용하면 객체를 손쉽게 병합 또는 변경할 수 있다.
// 객체의 병합
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(add); // { x : 1, y : 2, z : 0 }

이는 Object.assign 메소드를 사용해도 동일한 작업을 할 수 있다.

// 객체의 병합
const merged = Object.assign({}, { x : 1, y : 2 }, { y : 10, z : 3});
console.log(merged); // { 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(add); // { x : 1, y : 2, z : 0 }

또한 Spread 연산자를 사용하면 유사 배열 객체를 배열로 손쉽게 변환할 수 있다.

const htmlCollection = document.getElementsByTagName('li');

// 유사 배열인 HTMLCollection을 배열로 변환한다.
const newArray = [...htmlCollection]; // Spread 연산자

// ES6의 Array.from 메소드를 사용할 숟 ㅗ있다.
// const newArray = Array.from(htmlCollection);


다음은 객체 리터럴 프로퍼티 기능의 확장에 대해서 알아보도록 하겠습니다.

읽어주셔서 감사합니다ㅎㅎ


'ECMAScript 6' 카테고리의 다른 글

디스트럭처링  (0) 2019.08.14
객체 리터럴 프로퍼티 기능 확장  (0) 2019.08.13
Rest 파라미터  (0) 2019.08.11
화살표 함수 (=>)  (0) 2019.08.10
ES6 템플릿 리터럴  (0) 2019.08.09