배열은 모든 요소를 spread operator로 풀어서 새로운 배열에 넣는 방법은 아래와 같다.
const arr = [7, 8, 9];
const badNewArr = [1, 2, arr[0], arr[1], arr[2]];
console.log(badNewArr);
const newArr = [1, 2, ...arr];
console.log(newArr); // [1, 2, 7, 8, 9]
이미 존재하는 배열에 다른 배열의 원소들을 하나씩 넣어주고 싶으면 위의 코드에 badNewArr처럼 일일이 원소들을 넣어주는 것도 가능하지만 간편하게 spread opertaor를 사용할 수 있다. ...arr
이라고 써주면 arr 배열에 들어있는 7,8,9가 원소로 들어가게 되는 것이다. 여기서 ...를 빼고 arr만 써주면 arr 자체가 배열의 한 요소로 들어가게 된다.
const newMenu = [...restaurant.mainMenu, 'Gnocci'];
console.log(newMenu);
위의 코드처럼 newMenu라는 배열에 restaurant.mainMenu의 원소들이 차례로 들어가고 그 뒤에 'Gnocci'가 배열에 추가된다. 이때 다른 배열에 'Gnocci'와 같이 추가되었다고 해도 원래의 restaurant.mainMenu 배열은 변형되지 않는다.
Spread 연산자는 배열의 모든 요소를 가져온다. 새로운 변수를 생성하지 않고, 쉼표로 구분된 값이 필요한 곳에서만 사용할 수 있다.
배열, 문자열, map, set은 iterable 객체(반복 가능한 것들)이지만, 일반객체는 iterable이 아니다. Spread 연산자는 iterable 객체에 사용할 수 있다. 문자열도 iterable이기 때문에 다음과 같은 코드가 가능하다.
const str = 'Jonas';
const letters = [...str, '', 'S.'];
console.log(letters);
하지만 다음과 같은 코드는 불가능하다.
console.log(`${...str} Lee`);
그 이유는 쉼표로 구분된 여러 값은 함수에 인수로 전달할 때나 새로운 배열을 만들 때만 사용되기 때문이다
그럼 spread operator를 함수에 인수로 전달하는 예시를 한 번 살펴보도록 하자.
orderPasta: function (ing1, ing2, ing3) {
console.log(
`Here is your delicious pasta with${ing1},${ing2} and ${ing3}`);
}
위와 같은 함수를 추가한 뒤
const ingredients = [
prompt("Let's make pasta! Ingredients 1?"),
prompt('Ingredients 2?'),
prompt('Ingredients 3'),
];
이렇게 Ingredient 값을 받아온 다음,
restaurant.orderPasta(ingredients[0], ingredients[1], ingredients[2]);
or
restaurant.orderPasta(...ingredients);
이렇게 함수를 호출하면 된다. 위에 객체는 iterable하지 않다고 썼는데, 이 부분이 잘 이해가 가지 않아서 검색해본 결과, 다음과 같이 이해하면 된다. spread operator를 쓸 수 있다는 건 결국 내부에서 반복자를 사용해 원소들을 하나씩 추출하는 것이기 때문에 iterable 객체에서만 적용될 수 있다.
그래서 예를 들어 배열은 그게 가능하지만 일반 객체는 아래와 같이 안에 있는 원소들을 풀어서 뽑아 줄 수 없다.
const obj = { a: 1, b: 2 };
console.log(...obj); // Error: obj is not iterable
즉 위의 코드와 같이 객체로 되어있는걸 ...obj로 풀어서 써줄 수 없다는 것이다.
그런데 ES2018부터 object에서 spread operator를 쓸 수 있게 되었는데, 여기서 위의 예시처럼 객체 자체를 풀어서 쓸 수 있다는 것이 아니라, 객체 안의 속성을 복사하거나 합칠 때 사용한다.
예를 들어 아래의 코드를 보자.
const newRestaurant = { foundedIn: 1998, ...restaurant, founder: 'Juyeon' };
console.log(newRestaurant);
이렇게 쓰면 restaurant이라는 객체에 foundedIn과 founder라는 속성을 추가해 합쳐 줄 때 spread operator를 쓰는걸 볼 수 있다.속성을 복사하는 것도 아래와 같이 가능하다.
const restaurantCopy = { ...restaurant };
restaurantCopy.name = 'Ristorante Roma';
console.log(restaurantCopy.name);
console.log(restaurant.name);
이렇게 restaurant 객체를 restaurantCopy라는 이름으로 복사해준 뒤, 복사한 객체에 name 속성을 추가해 줄 수 있다.