ES6에서 도입된 Spread와 Rest 문법은 똑같이 생겼다.
다만 쓰이는 상황에 따라서 둘을 구분하기 때문에 확실하게 정리해보고자 한다.
1. Spread (전개 구문)
Spread는 배열, 문자열 등의 Iterable 한 요소들을 개별 요소로 분리할 수 있다.
주로 객체나 배열의 연결, 복사 등의 용도로 유용하게 쓰인다.
(참고로 객체는 Iterable이 아니지만 ES9부터 Spread 사용이 가능해졌다.)
1) 배열 결합
기존엔 두 배열을 합치는 데에 concat()
를 이용했었다.
하지만 ES6에선 Spread 연산자를 이용하여 좀 더 쉬게 배열을 합칠 수 있다.
// ES5 - concat()
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr = arr1.concat(arr2); // [ 1, 2, 3, 4, 5, 6 ]
// ES6 - Spread
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr = [...arr1, ...arr2]; // [ 1, 2, 3, 4, 5, 6 ]
또한 Spread는 다양한 형태의 배열 결합도 간단하게 구현할 수 있다.
const arr1 = [1, 2];
const arr2 = [0, ...arr1, 3, 4];
console.log(arr2); // [0, 1, 2, 3, 4]
2) 배열 복사
JavaScript는 배열을 새로운 변수에 할당하면 기존 배열을 참조하게 된다.
그래서 새로운 배열을 변경하면 원본 배열 역시 변경된다.
배열 참조가 아닌 배열 복사를 원한다면 기존에는 slice()
또는 map()
을 사용하였다.
그러나 Spread 연산자를 사용하면 쉽게 배열을 복사할 수 있다.
(참고로 Spread는 shallow copy이다.)
// ES5 - slice()
var arr1 = [1, 2, 3];
var arr2 = arr1.slice();
// ES5 - map()
var arr1 = [1, 2, 3];
var arr2 = arr1.map((item) => item);
// ES6 - Spread
const arr1 = [1, 2, 3];
const arr2 = [...arr1];
3) 객체에서의 Spread Operator
원래 객체는 Iterable이 아니라서 Spread를 사용하면 에러가 발생했다.
const obj = { name: 'John', age: '20' };
console.log(...obj); // TypeError: obj is not iterable
하지만 ES2018(ES9)에서 객체와 관련된 Spread Opeator가 추가되었다.
const obj1 = { name: 'John', age: '20' };
const obj2 = { name: 'Tom', age: '23' };
const clonedObj = { ...obj1 };
// Object { name: 'John', age: '20 }
const mergedObj = { ...obj1, ...obj2 };
// Object { name: 'John', age: '20', name: 'Tom', age: '23' }
4) Immutable (불변성)
Spread 연산자는 특히 React에서 불변성(immutable) 유지하는 데에 자주 사용된다.
Spread를 통해 객체를 업데이트하면 얻을 수 있는 장점은 다음과 같다.
- newObj가 obj와 서로 다르다는 결과를 통해 상태 변화를 감지할 수 있다.
- obj의 상태가 변경되지 않아 원본의 불변성을 유지할 수 있다.
const obj = { name: 'John', age: '20', flag: 'true', foo: 'bar' };
const newObj = { ...obj1, name: 'Alice' };
// Object { name: 'Alice', age: '20', flag: 'true', foo: 'bar' }
console.log(obj === newObj); // false
2. Rest (나머지 매개변수)
1) 함수의 Rest Parameter
기존 JavaScript에서는 함수의 매개변수로 배열을 받으려면 arguments
라는 유사 배열을 활용했다.
하지만 ES6의 Rest Parameter를 이용하면 함수의 매개변수들을 쉽게 배열로 만들 수 있다.
(단 Rest parameter는 항상 제일 마지막에 위치해야 한다.)
// ES5 - arguments
function add() {
var i = 0;
var sum = 0;
for (i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(add(1, 2, 3, 4)); // 10
// ES6 - Rest Parameter
function add(...rest) {
let sum = 0;
for (let item of rest) {
sum += item;
}
return sum;
}
console.log(add(1, 2, 3, 4)); // 10
2) 함수 호출 인자로 사용
기존에는 배열 형태를 함수의 인자로 전달하려면 직접 풀거나 apply()
를 사용했다.
하지만 Spread operator를 이용하면 배열 형태를 바로 함수 인자로 전달할 수 있습니다.
// ES5 - apply()
var args = [1, 2, 3, 4];
Math.max.apply(Math, args); // 4
// ES6 - Spread
const args = [1, 2, 3, 4];
Math.max(...args); // 4
3) Destructuring
Spread는 Destructuring(구조 분해 할당)에서 응용될 수 있다.
Destructuring에 대해 자세히 알고싶으면 아래 포스팅을 참고하면 된다.
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest); // [30, 40, 50]
'프론트엔드 > JavaScript' 카테고리의 다른 글
[JavaScript] this (2) | 2022.01.05 |
---|---|
[JavaScript] Prototype (0) | 2022.01.05 |
[JavaScript] var, let, const 차이 (0) | 2021.12.14 |
[JavaScript] 구조 분해 할당 (Destructing) (0) | 2021.12.09 |
[JavaScript] axios와 fetch 차이 (0) | 2021.12.09 |