스프레드 문법은 말 그대로 이터러블한 자료구조들을 펼치는 문법이다.
...
을 이용해서 펼칠 수 있다.
console.log(...[1, 2, 3]); // 1 2 3
console.log(...'HELLO'); // H E L L O
console.log(...{ a: 1 }); // TypeError: Spread syntax requires ...iterable[Symbol.iterator] to be a function
객체는
[Symbol.iterator]
가 없기 때문에 불가능한 모습을 볼 수 있다.
이 때 스프레드 문법은 이티러블한 객체를 나열하는 것일 뿐, 새로운 값을 생성하는 연산자가 아니다.
const arr = [1,2,3]
const spread = ...arr // SyntaxError: Unexpected token '...'
마치 Rest
문법과 비슷한 것처럼 느껴지지만 정 반대의 내용이다.
Rest
문법과 Spread
문법Rest
문법은 나열되어 있는 인수들을 하나의 배열로 만들어주는 문법이였다.
몇 개의 인수가 들어올지 모르는 함수에서
function sum() {
const arr = Array.from(arguments);
return arr.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
이렇게 arugment
프로퍼티를 가지고 접근하는 방식에서
function sum(...rest) {
return rest.reduce((pre, cur) => pre + cur, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
몇 개의 인수가 들어올지 모르는 경우에서 나열된 인수들을 배열 형태로 나열하는게 Rest
문법이였다면
Spread
문법은 오히려 자료구조를 해체하여 나열하는 것이다.
예를 들어
console.log(Math.max(1, 2, 3, 4, 5)); // 5
Math.max
같은 경우엔 나열되어있는 인수들 중 최대 값을 설정하는 것인데
const arr = [1, 2, 3, 4, 5];
console.log(Math.max(arr)); // NaN
배열 자체는 하나의 객체이기 때문에 최대값을 구하는게 불가능하다.
이를 해결하기 위해
const arr = [1, 2, 3, 4, 5];
console.log(Math.max(...arr)); // 5
값들이 담긴 자료구조를 오히려 나열해주는 것이 Spread
문법이다.
concat
이전 챕터인 배열
파트에서 spread
문법을 사용했었다.
두 가지 배열을 합쳐 하나의 배열을 만들고 싶을 때는 concat
문법을 사용했었다.
const arr1 = [1, 2];
const arr2 = [3, 4];
const result = arr1.concat(arr2);
console.log(result); // [1,2,3,4]
하지만 이는 Array.prototype.concat
메소드를 호출하는 것이기 때문에 오버헤드가 존재한다.
이를 spread
문법을 통해 더 빠르고 효율적으로 할 수 있다.
const arr1 = [1, 2];
const arr2 = [3, 4];
const result = [...arr1, ...arr2];
console.log(result); // [ 1, 2, 3, 4 ]
splice
splice
는 특정 인덱스부터 값을 삭제하거나, 추가하는 것이 가능했다.
const arr1 = [1, 2];
const arr2 = [3, 4];
arr1.splice(1, 0, arr2);
console.log(arr1); // [ 1, [ 3, 4 ], 2 ]
1번째 인덱스부터 arr2
에 담긴 값들을 넣고 싶어서 사용하면 이처럼 객체 자체가 들어간다.
하지만 Spread
문법을 사용하면 ?
const arr1 = [1, 2];
const arr2 = [3, 4];
arr1.splice(1, 0, ...arr2);
console.log(arr1); // [ 1, 3, 4, 2 ]
값들이 나열되어 들어가기 때문에 잘 들어간다
배열을 복사 할 때는 slice
를 이용한다고 했다.
const arr = [1, 2, 3, 4, 5];
const newarr = arr.slice();
console.log(newarr); // [1, 2, 3, 4, 5]
console.log(arr === newarr); // false
slice
는 얕은 복사이다.
const arr = [1, 2, 3, 4, 5];
const newarr = [...arr]; // [1, 2, 3, 4, 5]
console.log(arr === newarr); // false
이 또한 spread
문법을 이용해서 쉽게 할 수 있다.
const obj = { a: 1, b: 2 };
const newobj = { ...obj };
console.log(newobj); // { a: 1, b: 2 }
console.log(newobj === obj); // false
스프레드 문법을 이용해 얕은 복사를 시행 할 수 있다.
얕은 복사이기 때문에 중첩 되어 있는 객체는 동일하게 참조한다.
const obj = {
gender: 'female',
information: {
name: 'lee',
age: 16,
},
};
const newobj = { ...obj };
console.log(newobj === obj); // false
console.log(newobj.information === obj.information); // true
엥 ? 객체는 이터러블 객체가 아니라 스프레드 문법 안되는거 아닌가요?
스프레드를 이용해 프로퍼티를 지정하는 스프레드 프로퍼티 제안은 일반 객체 대상으로도 허용된다.
스프레드 문법이 익숙해지면 유용하게 사용할 수 있을 것 같네요 좋은 글 감사합니다.