자바스크립트(JavaScript) - Spread Syntax (전개 구문)

JavaScript

Posted by kwon on 2020-08-16

Spread Syntax (전개 구문)

  • Spread Syntax(전개 구문)는 es6에 추가된 문법으로 iterable 객체를 개별 요소로 분리시키는 문법이다.
    • iterable - 배열, 문자열, set, map 등..

Spread 문법의 사용방법

함수 호출

1
2
3
4
5
6
7
8
const sum = (a, b, c, d) => {
return a + b + c + d;
}

const kwon = ['k', 'w', 'o', 'n'];

console.log(sum(...kwon));
// 출력 : kwon

위와 같이 함수를 호출할 때 매개변수로 전개 연산자를 사용하여 배열을 넘겨 각각의 인자에 배열의 원소를 할당할 수 있다. 이 때, 물론 매개변수의 개수가 일치해야 한다.

배열 리터럴과 문자열

두 배열을 연결하는 경우 Array.prototype.concat() 을 사용하여 기존 배열에 새로운 배열의 요소를 추가하여 새로운 배열을 만들 수 있었다.

1
2
3
4
5
6
const arr1 = ['kwon', 'kim', 'jung'];
const arr2 = ['jo', 'park', 'lee'];

const arr3 = arr1.concat(arr2)
console.log(arr3);
// 출력 : [ 'kwon', 'kim', 'jung', 'jo', 'park', 'lee' ]

위의 코드를 전개 구문을 사용하는 경우 간편하게 작성할 수 있다.

1
2
3
4
5
6
const arr1 = ['kwon', 'kim', 'jung'];
const arr2 = ['jo', 'park', 'lee'];

const arr3 = [...arr1, ...arr2];
console.log(arr3);
// 출력 : [ 'kwon', 'kim', 'jung', 'jo', 'park', 'lee' ]

또한 push, splice 등을 활용, 대신하여 다양한 방식으로 배열을 다룰 수 있다.

1
2
3
4
5
6
const arr1 = ['kwon', 'kim', 'jung'];
const arr2 = ['jo', 'park', 'lee'];

arr1.push(...arr2);
console.log(arr1);
// 출력 : [ 'kwon', 'kim', 'jung', 'jo', 'park', 'lee' ]
1
2
3
4
5
6
7
8
9
const arr1 = ['kwon', 'kim', 'jung'];
const arr2 = ['jo', 'park', 'lee'];

const arr3 = [...arr2, 'kwon', 'kim', 'jung'];
console.log(arr3);
// 출력 : [ 'jo', 'park', 'lee', 'kwon', 'kim', 'jung' ]
const arr4 = ['kwon', ...arr2, 'kim', 'jung'];
console.log(arr4);
// 출력 : [ 'kwon', 'jo', 'park', 'lee', 'kim', 'jung' ]

문자열도 iterable 이기 때문에 전개구문을 사용 가능하다.

1
2
3
4
5
const str = 'abcdefg';
console.log(str.split('')); // 기존 방식
// 출력 : ['a', 'b', 'c', 'd', 'e', 'f', 'g']
console.log([...str]); // 전개 구문 적용
// 출력 : ['a', 'b', 'c', 'd', 'e', 'f', 'g']

배열 복사

1
2
3
4
5
6
7
const arr1 = ['kwon', 'kim', 'jung'];
const arr2 = [...arr1];
console.log(arr2);
// 출력 : [ 'kwon', 'kim', 'jung' ]
arr2.push('jo');
console.log(arr1);
// 출력 : [ 'kwon', 'kim', 'jung' ]

전개 구문을 통해 배열을 복사하는 경우 깊은 복사를 할 수 있다. 깊은 복사는 복사를 통해 생성된 배열을 변경하여도 원본 배열에 영향이 없어야 한다. 하지만, 배열 안에 또 배열or객체가 있는 경우에는 깊은 복사가 제대로 이루어지지 않는다. 즉, (원시 타입으로 구성된) 1차원 배열에서만 전개 구문을 통해 깊은 복사를 할 수 있다.

1
2
3
4
5
const arr1 = [['kwon', 'kim'], 'jung'];
const arr2 = [...arr1];
arr2[0].pop();
console.log(arr1);
// 출력 : [ [ 'kwon' ], 'jung' ]

위와 같이 배열 안에 있는 배열을 변경하는 경우에는 원본 배열에도 영향을 미치는 것을 볼 수 있다.

객체 리터럴

1
2
3
4
const obj1 = { key1: 'val1', key2: 'val2' };
const obj2 = { ...obj1, key3: 'val3' };
console.log(obj2);
// 출력 : { key1: 'val1', key2: 'val2', key3: 'val3' }

객체에서도 전개 구문을 사용하여 객체를 정의할 수 있다.
하지만, 객체 리터럴에서와 달리 함수 호출과 배열 리터럴에서의 전개 구문은 반드시 iterable 이어야 사용이 가능하다는 것이다.

1
2
3
4
const obj1 = { key1: 'val1', key2: 'val2' };
const arr1 = ['kwon', 'kim', 'jung', ...obj1];
console.log(arr1);
// 에러 : obj1 is not iterable

Spread Syntax(전개 구문) 활용

나머지 매개변수

rest 파라미터는 함수의 마지막 파라미터 앞에 ... 을 붙여 모드 나머지 인수를 유사 배열이 아닌, ‘표준’ 자바스크립트 배열로 대체한다. (arguments 객체(유사배열)와 차이점)

특정 인수의 갯수를 지정할 필요없이 들어온 인수를 배열로 전달받을 수 있어 유용하다.

1
2
3
4
5
6
7
const fn1 = (a, b, ...rest) => {
console.log(a);
console.log(b);
console.log(rest);
}

fn1('kwon', 'kim', 'jo', 'jung', 'lee');

출력

1
2
3
kwon
kim
[ 'jo', 'jung', 'lee' ]

아래는 모든 인자를 누적하여 합을 리턴해주는 함수이다. ( Array.prototype.reduce() 사용)

1
2
3
4
const sumAll = (...args) => args.reduce((acc, cur) => acc + cur, 0);
console.log(sumAll(1, 2, 3));
console.log(sumAll(1, 2, 3, 4, 5));
console.log(sumAll(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

매개변수를 몇 개로 받더라도 모두 배열로 넘겨받아 정상적으로 처리되는 것을 볼 수 있다.
나머지 매개변수를 사용할 때 주의할 점은 항상 가장 마지막 파라미터로 나머지 매개변수를 사용해야 한다는 점이다.

1
2
3
4
const fn1 = (arg1, ...rest, arg2) => {
// ...
}
// 에러 : Rest parameter must be last formal parameter

위와 같이 중간에 나머지 매개변수를 넣게 되면 에러가 발생한다.

배열에서 중복 원소 제거

1
2
3
4
const arr = [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 7];
const newArr = [...new Set(arr)];
console.log(newArr);
// 출력 : [1, 2, 3, 4, 5, 6, 7]

Set과 함께 사용하면 위와 같이 중복을 제거하는 것도 가능하다.

구조 분해 할당

1
2
3
const [ first, second, ...rest ] = ['kwon', 'kim', 'jo', 'jung', 'lee'];
console.log(first, second); // 출력 : kwon kim
console.log(rest); // 출력 : [ 'jo', 'jung', 'lee' ]

구조 분해 할당에서도 활용이 가능한데, 배열에서 구조 분해 할당은 index 값이 기준이 된다. 또한 나머지 매개변수와 마찬가지로 마지막 요소로 위치시키지 않으면 다음과 같은 에러가 발생한다.

  • SyntaxError: Rest element must be last element

참조
https://chanspark.github.io/2017/11/28/ES6-%EA%BF%80%ED%8C%81.html
https://jongbeom-dev.tistory.com/117
https://mber.tistory.com/14
https://ko.javascript.info/rest-parameters-spread
https://velog.io/@kwonh/ES6-%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%BB%AC%EB%A0%89%EC%85%98-Array2-%EB%B0%B0%EC%97%B4-%ED%8E%BC%EC%B9%A8%EC%97%B0%EC%82%B0%EC%9E%90%EC%A0%84%EA%B0%9C%EC%97%B0%EC%82%B0%EC%9E%90-Spread-Syntax-Spread-Operator-1y6chdfg