[자바스크립트] 전개(spread) 연산자
전개 연산자란
전개 연산자는 ECMAScript2015에서 도입된 문법이다. 전개란 펼치다라는 의미로, 전개 연산자를 사용하면 의미 그대로 객체 혹은 배열을 펼칠 수 있게 해 준다.
전개 구문을 배열이나 객체 앞에 점 3개(...)를 붙여주면 된다.
배열 : ...[] 객체 : ...{}
전개 연산자를 사용하면 펼쳐진 객체나 배열을 반환하기 때문에 객체 또는 배열로 담아야 한다.
//객체 spread
{ ...{} }
//배열 spread
[ ...[] ]
{ ...[] }
객체는 객체에만 담을 수 있고, 배열은 객체와 배열 두 곳에 다 담을 수 있다. 또한, 전개 연산자를 통해 각각의 데이터만 복사해서 뽑아오는 것이기 때문에 원본 객체와 배열이 변경되지 않는다.
ES5 vs ES6
배열 합치기
ES5에서는 배열의 내용을 합쳐 새로운 배열을 만들기 위해서 concat 메소드를 사용하였다.
//concat
//ES5 -> 배열 연결 메소드
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = arr1.concat(arr2);
console.log(arr3) //[1, 2, 3, 4, 5, 6]
위의 예제를 ES6에서 나온 전개 연산자를 사용하면 아래와 같이 코딩할 수 있다.
//전개 연산자
//ES6에서 도입
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = [...arr1, ...arr2]
console.log(arr3) //[1, 2, 3, 4, 5, 6]
concat 메소드를 사용할 때 보다 코드가 간결해지고 가독성이 좋아진 것을 볼 수 있다. 또한 배열의 끝에서만 합칠 수 있는 concat메소드와는 달리 전개 연산자를 사용하면 배열에 어느 위치든지 자유롭게 배열을 추가할 수 있다.
//concat
//배열의 '끝'에 합침
const arr1 = [1, 2, 6]
const arr2 = [3, 4, 5]
//위의 코드를 오름차순으로 합쳐서 출력
//먼저 합친 다음, sort() 사용
console.log(arr1.concat(arr2).sort()); // [1, 2, 3, 4, 5, 6]
//전개연산자
//아무곳에나 넣을 수 있음
console.log(arr1.splice(2, 0, ...arr2)); // [1, 2, 3, 4, 5, 6]
// === [1, 2, ...arr2, 6]
배열 이어붙이기
배열에 요소를 추가하기 위해서는 push 메소드를 사용을 한다. 이 때에 다른 배열의 요소들의 값을 추가하여 이어붙이고 싶다면 어떻게 해야 할까?
ES5에서는 Array 객체의 프로토타입 메서드인 push.apply를 사용해야 한다.
//배열 이어붙이기
//배열 요소 추가 => push
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr1.push(arr2); // <= [1, 2, 3, [4, 5, 6]] : 2차원 배열이 되어버림
//Array.prototype.push.apply
Array.prototype.push.apply(arr1, arr2); // <= [1, 2, 3, 4, 5, 6]
위의 예제에서 ES6에 도입된 전개 연산자를 사용하면, 기존의 push 메소드를 사용할 수 있어 훨씬 간결하고 쉽게 구현이 가능해진다.
//배열 이어붙이기
//전개연산자 사용 => push 사용 가능
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr1.push(...arr2); // <= [1, 2, 3, 4, 5, 6]
배열의 전개
전개연산자로 배열을 펼쳤을 때, 해당 데이터는 배열안에 담아도 되고 객체 안에 담아도 된다. 객체에 담기게 될 시, 프로퍼티 네임(key)은 배열의 인덱스가 할당된다.
// 배열의 전개연산자
const fruits = ['apple', 'peach', 'melon'];
// 배열에 담기
const arr = [ ...fruits ];
console.log(arr); //['apple', 'peach', 'melon']
// 객체에 담기
const obj = { ...fruits };
console.log(obj); //{ 0 : 'apple', 1 : 'peach', 2 : 'melon' };
만약 2차원 배열에 전개연산자를 사용한다면 어떻게 될까? 2차원 배열에 전개연산자를 사용할 경우에는 1차원 배열 껍데기만 벗겨진다.
// 2차원 배열에서 전개 연산자 사용
const arr = [ 2, [3, 4, 5]];
const arr1 = [ 1, ...arr, 6 ];
console.log(arr1); // [1, 2, [3, 4, 5], 6];
arr의 바깥의 첫 배열 껍데기([]) 만 벗겨줘서 들어간 것을 확인 할 수 있다. 즉, 전개연산자를 사용은 1차원에서만 유효하다.
객체의 전개
객체를 전개 연산자로 통해 펼쳤을 때, 해당 데이터들은 객체에만 담길 수 있다.
// 객체의 전개 연산자
const obj = {
name : 'John',
age : 23,
}
const obj1 = {
...obj,
//새로운 프로퍼티를 추가하는 것도 가능!!
address : 'Seoul',
}
console.log(obj1); // { name : 'John', age : 23, address : 'Seoul' }
객체는 순서를 보장하지 않기 때문에 obj를 address 프로퍼티 앞에서 펼쳤다고 obj의 프로퍼티들의 순서가 먼저라는 보장은 없다!!
그 외의 전개
Argument
인수 값으로 전개 연산자를 통해 전개한 데이터를 넘겨줄 수 있다.
// 인수값 <= 전개한 배열
fucntion sum(num1, num2, num3) {
conosle.log(num1 + num + num3);
}
const arr = [1, 2, 3];
sum(...arr); // === sum(1, 2, 3) => 6
//파리미터값 보다 많은 인수 값이 들어갈때
const arr1 = [1, 2, 3, 4];
sum(...arr); // === sum(1, 2, 3) => 6
Parameter
파라미터로도 전개 연산자를 사용할 수 있다. 전개 연산자를 이용한 파라미터를 rest parameter라고도 부른다.
//함수의 파라미터로도 사용가능
//rest parameter라고도 함
function paraFunc(num1, num2, ...num3) {
console.log(num3);
}
//파라미터 이상의 인수 값을 넘길 시,
//초과하는 인수는 모두 num3에 배열로 형식으로 들어감
paraFunc(1, 2, 3, 4, 5); // [3, 4, 5]
paraFunc(1, 2, 3); // [3]
paraFunc(1, 2, ...[3, 4, 5]); // [3, 4, 5]
rest parameter를 사용할 때 주의할 점은, 파라미터의 제일 마지막에 위치하여야 하는 것이다. 왜냐하면, rest parameter는 자신의 순서부터 이후에 들어오는 모든 값을 배열에 저장하기 때문이다.
//함수의 마지막 파라미터로만 선언해야 함
function paraFunc(num1, ...num3, num2) {
console.log(num2);
}
paraFunc(1, 2, 3, 4, 5); // undefined
문자열
문자열도 전개 연산자를 사용하여 펼칠 수 있고 이 때에 펼친 데이터는 배열, 객체 모두에 담을 수 있다.
//문자열 전개
const strings = 'abcdefg';
const strings2 = {...strings}
console.log(strings2) // {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g'}
const strings3 = [...strings]
console.log(strings3) // (7) ['a', 'b', 'c', 'd', 'e', 'f', 'g']