ES6 주요문법 (Spread / Rest ...)

Chunli91·2022년 9월 7일
0

자바스크립트

목록 보기
17/24
post-custom-banner

1. 전개 구문(Spread Syntax)

전개 구문(Spread Syntax)은 ECMAScript6(2015)에서 새로 추가된 문법으로, 간단하게 이 문법은 문법 이름 그대로 객체 혹은 배열들을 펼칠 수 있게 해준다.

// 펼칠 대상이 객체인 경우
{...obj}
 
// 펼칠 대상이 배열인 경우
[...arr]
// 혹은
{...arr}

전개 구문의 문법 자체는 정말 간단하다. 그저 배열이나 객체 앞에 점 세 개를 붙여주면 된다.
단, 위 코드에서 확인할 수 있는 것처럼 펼쳐진 객체나 배열을 담을 바구니가 필요하다.
객체는 객체로, 배열은 객체나 배열로 담아낼 수 있다.

1-1. ES5 vs ES6 배열 문법

[ES5 배열 내용 조합]
ES5에서는 배열의 내용을 합쳐 새로운 배열을 만들기 위해서 concat 메소드를 활용했었다.
arr1 배열에 concat 메소드를 사용하여, 배열 arr2와 arr3를 배열에 이어붙였다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
const arrWrap = arr1.concat(arr2, arr3);
 
console.log(arrWrap); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

[ ES6 배열 내용 조합 ]
전개 연산자를 활용하여 새로운 배열을 만들었다.

concat 메소드를 사용한 코드보다 간결하고, 가독성도 개선되었다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [7, 8, 9];
const arrWrap = [...arr1, ...arr2, ...arr3];
 
console.log(arrWrap); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

concat 메서드는 인자로 전달받은 값 순으로 기존 배열 끝에서부터 값을 추가하지만, 전개 연산자는 아래처럼 배열의 아무 곳에나 추가 할 수 있다는 장점이 있다.

const arr = [4, 5, 6];
const arrWrap = [1, 2, 3, ...arr, 7, 8, 9]
 
console.log(arrWrap); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

2. 펼칠 대상이 배열인 경우

const myArray1 = ['Canna', 'Cuzz', 'Faker', 'Teddy', 'Effort'];
const myArray2 = [...myArray1]; // ...myArray1 : 'Canna', 'Cuzz', 'Faker', 'Teddy', 'Effort'
 
console.log(myArray1); // ["Canna", "Cuzz", "Faker", "Teddy", "Effort"]
console.log(myArray2); // ["Canna", "Cuzz", "Faker", "Teddy", "Effort"]
 
console.log(myArray1 === myArray2); // false

배열도 동일하게 전개구문을 활용해서 배열을 펼쳐 새로운 배열을 만들 수 있고, 두 배열을 비교하면 false가 출력되면서 서로 다른 독립적인 배열이 되는 모습도 확인할 수가 있다.

const myArray = ['Canna', 'Cuzz', 'Faker', 'Teddy', 'Effort'];
 
const myObject = {...myArray};
 
console.log(myArray); // ["Canna", "Cuzz", "Faker", "Teddy", "Effort"]
console.log(myObject); // {0: "Canna", 1: "Cuzz", 2: "Faker", 3: "Teddy", 4: "Effort"}

만약 펼친 배열을 중괄호로 감싸서 객체로 만든다면, 각 요소는 프로퍼티 값이 되고, 배열의 index가 프로퍼티 네임이 된다.

2-1. 전개 연산자로 할당하면 2차원 형태가 되지 않는다.

concat 메소드로 새로운 배열을 만들어내는 것이 아닌, 기존 배열 요소에 값을 추가한다면 push 메소드를 사용할 것이다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5];
arr1.push(arr2);
 
console.log(arr1); // [1, 2, 3, [4, 5]]

arr1 배열에 arr2 배열을 할당했지만 arr2 배열 전체가 들어가 2차원 배열이 되었다.
이 경우 기존 자바스크립트에서는 배열 객체의 프로토타입 매서드인 push.apply를 사용해야 한다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5];
Array.prototype.push.apply(arr1, arr2);
 
console.log(arr1); // [1, 2, 3, 4, 5]

원하는 결과를 얻었지만 코드가 복잡하다.
하지만 전개 연산자를 활용하면 쉽게 구현이 가능하다.

const arr1 = [1, 2, 3];
const arr2 = [4, 5];
arr1.push(...arr2);
 
console.log(arr1); // [1, 2, 3, 4, 5]

2-2. 반대로 전개 연산자를 이용한 복사에는 1차원에서만 유효하다.

위에서 전개 연산자로 할당하면 2차원 배열이 되지 않는다고 했다.

하지만 2차원 이상의 배열을 할당할 땐 1차원 요소만 같은 1차원 레벨로 할당이 되고 2차원 이상의 배열은 그대로 들어간다.

const arr1 = [4, 5, [6, 7]];
const arr2 = [1, 2, 3, ...arr1];
console.log(arr2); // [1, 2, 3, 4, 5, [6, 7]]

2-3. 기존 배열을 보존해야 할 때 유용하다.

[ES5 배열 요소를 역순으로 변경]

reverse 메소드는 배열의 각 요소를 역순으로 바꾸는 메소드인데, 기존 배열도 바꿔버리는 단점이 있다.

const arr1 = [1, 2, 3];
const arr2 = arr1.reverse();
 
console.log(arr1); // [3, 2, 1]
console.log(arr2); // [3, 2, 1]

원본 배열을 수정할 의도가 있었으면 문제가 되지 않지만, 원본 배열은 그대로 두고 배열 요소의 순서를 뒤집은 새로운 배열이 필요하다면 상황이 복잡해진다.

이 상황에서 전개 연산자를 사용하면 편리해진다.

[ES6 배열 요소를 역순으로 변경]

const arr1 = [1, 2, 3];
const arr2 = [...arr1].reverse(); // arr1을 복사하고 reverse하는거라 원본은 아무 문제 없다.
 
console.log(arr1); // [1, 2, 3]
console.log(arr2); // [3, 2, 1]

전개 연산자는 원본 배열을 그대로 유지하면서 새로운 배열을 만든다.

원본 배열은 그대로 유지하면서 새로운 배열을 만들었다.

2-4. 배열의 나머지 요소를 할당할 수 있다.

비구조화 할당과 전개 연산자를 사용하여 배열의 나머지 요소를 할당 받을 수 있다.

const [first, second, ...rest] = [1, 2, 3, 4, 5];
 
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]

변수 first과 second의 각각의 인덱스 값에 맞는 값이 차례로 들어가고(1, 2), rest에는 할당 받지 못한 나머지 값들이 대입된다.

3. 펼칠 대상이 객체인 경우

const myObject1 = {
    laptop: 'MacBook Pro',
    tablet: 'iPad Pro 11'
}
 
const myObject2 = {...myObject1};
 
console.log(myObject1); // {laptop: "MacBook Pro", tablet: "iPad Pro 11"}
console.log(myObject2); // {laptop: "MacBook Pro", tablet: "iPad Pro 11"}
 
console.log(myObject1 === myObject2); // false
// 서로 다른 주소 값을 가진 독립적인 객체임을 확인할 수 있다.

위 코드 중 6번째 줄, myObject2에 할당하는 값을 보면 전개 구문을 활용하고 있다.
앞에 점 3개를 붙여서 myObject1을 펼친 것이다.

그러면 당연히 myObject2는 myObject1과 똑같은 모양의 프로퍼티를 갖게 되지만, 마지막 줄에서 보는 것과 같이 두 객체를 비교할 경우 false가 출력되면서 서로 다른 주소 값을 가진 독립적인 객체임을 확인할 수 있다.

또한 전개 구문을 활용하면 이렇게 다른 객체의 프로퍼티를 복사해오면서 추가로 프로퍼티를 작성할 수도 있다.

const myObject1 = {
    laptop: 'MacBook Pro',
    tablet: 'iPad Pro 11'
}
 
const myObject2 = {
    ...myObject1,
    phone: 'Galaxy Note 10'
};
 
console.log(myObject1); // {laptop: "MacBook Pro", tablet: "iPad Pro 11"}
console.log(myObject2); // {laptop: "MacBook Pro", tablet: "iPad Pro 11", phone: "Galaxy Note 10"}

3-1. 객체를 복사할 경우

const obj1 = {
  a: 'A',
  b: 'B'
};
const obj2 = {
  c: 'C',
  d: 'D'
};
const objWrap = {obj1, obj2};
console.log(objWrap);
/*
{
  obj1: {
    a: 'A',
    b: 'B'
  },
  obj2: {
    c: 'C',
    d: 'D'
  }
}
*/

obj1 객체와 obj2 객체를 하나의 objWrap 객체로 묶으면 객체 각각의 값이 아닌, 객체 자체가 들어가 2차원 객체가 되었다.

const obj1 = {
  a: 'A',
  b: 'B'
};
const obj2 = {
  c: 'C',
  d: 'D'
};
const objWrap = {...obj1, ...obj2};
console.log(objWrap);
/*
{
  a: 'A',
  b: 'B',
  c: 'C',
  d: 'D'
}
*/

전개 연산자를 사용하면 객체 자체가 할당되는 것이 아닌, 각각의 값이 할당 된다.

4. 펼칠 대상이 매개변수인 경우

4-1. 전개 연산자 로서 아규먼트 값을 넘기는 경우

  • 위에서 했듯이 배열 안에 있는 값들을 인수들 목록으로 풀어 넘겨주는 역할을 한다.
  • 리턴값 : 인수들 목록
let arr = [3, 5, 1];
 
alert( Math.max(...arr) ); // 5 (전개 연산자가 배열을 인수 리스트 바꿔주었습니다.)

4-2. 나머지 연산자로서 매개변수로 파라미터를 받는 경우

  • 매개변수에 전개 구문을 활용하면, 함수를 호출할 때 넘쳐나는(?) 인자들을 하나의 배열로 모아주는 매개변수로 활용할 수 있다.
  • 리턴값 : 배열
function sumAll(...args) { // args는 배열입니다.
  let sum = 0;
 
  for (let arg of args) sum += arg;
 
  return sum;
}
 
alert( sumAll(1) ); // 1
alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3) ); // 6
function showName(firstName, lastName, ...titles) {
  alert( firstName + ' ' + lastName ); // Julius Caesar
 
  // 나머지 인수들은 배열 titles에 할당됩니다.
  // titles = ["Consul", "Imperator"]
  
  alert( titles[0] ); // Consul
  alert( titles[1] ); // Imperator
  alert( titles.length ); // 2
}
 
showName("Julius", "Caesar", "Consul", "Imperator");

※ 단, 나머지 매개변수는 항상 마지막에 있어야 한다.

function f(arg1, ...rest, arg2) { // ...rest 후에 arg2가 있으면 안 됩니다.
  // 에러
}

4-3. 전개 연산자 매개변수 사용 패턴

인수 개수에 제한이 없는 함수를 만들 때 나머지 매개변수를 사용.

let fuc = function(...args) {
	// ...
}
 
func(1,2,3);
func(1,2,3,4,5);
func(1,2,3,4,5,6,7,8,9,10);

많은 수의 인수를 받는 함수에 배열을 전달할 때 전개 연산자를 사용.

const arg = [1,2,3,4,5,6,7,8,9,10];
const sum = function(...args) {
	console.log(args);
}
 
// 둘이 같다.
// 배열을 인수로 넘겨주는 apply()와 전개연산자를 이용해 배열을 인수로 치환한 call()
sum.apply(null, arg); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum.call(null, ...arg); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

5. 펼칠 대상이 문자열인 경우

놀랍게도 문자열도 spread 문법으로 산개 할 수 있다.
왜냐하면 문자열도 자바스크립트에선 하나의 객체로 취급되기 때문이다.

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']

★ 요약
...는 전개 연산자나 나머지 매개변수로 사용된다.
전개 연산자와 나머지 매개변수는 아래의 방법으로 구분할 수 있다.

  • 함수 호출 시 사용되면 배열을 목록으로 확장해주는 전개 연산자
  • 함수 매개변수의 끝에 있으면 인수 목록의 나머지를 배열로 모아주는 나머지 매개변수
profile
30대에 새로운 도전을 시도하는 사람입니다.
post-custom-banner

0개의 댓글