(17) Modern JavaScript - Spread 구분

반응형

Spread 구문은 ES2015에 등장한 새로운 문법이며

주로 배열을 다룰 때 유용하게 활용되고

아래와 같이 여러 개의 값을 하나로 묶은 배열을 다시 각각의 개별 값으로 펼치는 문법이다.

// Spread 구문 (Spread Syntax)
const number = [1, 2, 3];
console.log(number);

 

 

Spread 구문의 문법은 다음과 같다.

// Spread 구문 (Spread Syntax)
const number = [1, 2, 3];
console.log(...number);

위와 같이 마침표 (...)를 붙여주면 다음과 같은 결과를 볼 수 있다.

Spread 사용 전 과 후

Spread 적용 전에는 배열 형식으로 출력되지만

적용 후에는 숫자가 각각 출력되는 모습을 확인할 수 있는데

말 그대로 대괄호를 묶여서 number에 담겨있는 값들이

괄호가 벗겨지고 1,2,3처럼 각각 개별 값으로 펼쳐진 것이다.

 


그런데 마침표 세 개를 사용했던 문법이 하나 더 있었다.

바로, Rest parameter를 만들 때도 마침표 세 개를 사용했었는데

문법은 똑같지만 동작하는 방식이 완전히 다르다. 

function printArguments(...args) { // Rest Parameter? Spread ?
  for (const arg of args) {
    console.log(arg);
  }
  console.log(`--------------------------`);
}
printArguments("Jung", "Sang", "hwa");
printArguments("Shin");
printArguments("Chang", "Seop");

printArguments("Ronaldo", "Messi");
printArguments("Doran", "Oner", "Deft", "Keria");

 

레스트 파라미터여러 개의 아규먼트를 하나의 파라미터로 묶는 방식이고

스프레드 구문하나로 묶여있는 값을 각각의 개별 값으로 펼치는 방식이다.

이 두 문법의 차이를 잘 구분하고 넘어가자.


배열 Spread 하기

아무튼 Spread 구문은 배열에서 유용하게 활용된다고 했을 때,

배열을 좀 더 편리하게 복사할 수 있다.

예시로 아래의 코드를 살펴보면

const webPublishing = ["HTML", "CSS"];
const interactiveweb = webPublishing;

interactiveweb.push("JavaScript");

console.log(webPublishing);
console.log(interactiveweb);

객체 타입의 값들은 변수에 값이 직접 할당되는 것이 아니라 주소 값이 참조된다고 했을 때,

interactiveWeb이 webPublishing을 참조하기 때문에

interactiveWeb에서 "JavaScript"를 push 하더라도

코드를 실행해보면 webPublishing에도 "JavaScript"가 push된 모습을 확인할 수 있다.

(이해가 되지 않는다면 참조형에 대해 좀 더 알아보자 - Link)

 

(38) JavaScript - 자료형(심화) / 기본형과 참조형

기본형(Primitive Type) , 참조형 (Reference기본형은 객체를 제외한 나머지 자료형을 묶은 Number, String, boolean, null, undefined 가 속한다 우리가 어떤 값을 다룰 때 특별한 경우를 제외하면 모두 변수에 할

seop-e.tistory.com

 

 

그래서 이런 경우에는 slice 메소드를 활용해서 배열을 복사한다고 했을 때, 

 

(39) JavaScript - 자료형(심화) / 참조형 copy하기

참조형 값은 변수에 할당될 때 값 자체가 아닌 주소값이 할당된다고 했을 때, let number1 = [1, 2, 3] let number2 = number1 number2.push(4) console.log(number1); console.log(number2);▲ 코드를 보면 배열도 참조형이기

seop-e.tistory.com

아래와 같이 slice 메소드를 적용하면 interactiveWeb에서만 "JavaScript"가 push 된 것을 확인할 수 있다.

const webPublishing = ["HTML", "CSS"];
const interactiveweb = webPublishing.slice();

interactiveweb.push("JavaScript");

console.log(webPublishing);
console.log(interactiveweb);

 

이때 아래와 같이 Spread 구문을 활용하면 메소드를 복사할 수 있다.

const webPublishing = ["HTML", "CSS"];
const interactiveweb = [...webPublishing]; // Spread

interactiveweb.push("JavaScript");

console.log(webPublishing);
console.log(interactiveweb);

결과도 제대로 동작하는 모습을 확인할 수 있다.


심지어 Spread 구문을 사용할 때 아래와 같이 옆에 바로 요소를 추가하여

좀 더 직관적이고 간단하게 배열을 다룰 수 있다.

const webPublishing = ["HTML", "CSS"];
const interactiveweb = [...webPublishing, "JavaScript"]; // Spread

// interactiveweb.push("JavaScript");

console.log(webPublishing);
console.log(interactiveweb);

그리고 여러 배열을 합칠 때도 각 배열을 Spread 구문을 펼쳐서 

아래와 같이 두 배열이 합쳐진 새로운 배열을 간단하게 만들 수 있다.

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

물론 이 코드를 Spread 구문 없이 concat 메소드를 활용할 수 있지만

Spread 구문을 활용한 쪽이 변수에 담길 배열의 모습을

좀 더 직관적으로 보여주는 장점이 있다.


또한 함수를 호출할 때 아규먼트로 활용할 수 있다.

const introduce = (myName, birth, job) => {
  console.log("안녕하세요");
  console.log(`제 이름은 ${myName} 입니다.`);
  console.log(`제 생일은 ${birth} 입니다.`);
  console.log(`직업은 ${job} 입니다.`);
};
const myArr = ["섭이", "0101", "백수"];
introduce(...myArr);

위와 같이 여러 개의 파라미터가 있는 함수를 호출할 때

배열을 펼쳐서 (...myArr) 각각의 아규먼트로 사용할 수 있다.

 

단 위와 같이 아규먼트로 Spread 구문을 활용한 예시를 보고서 

Spread 구문 자체가 값이라고 생각할 수도 있지만

여러 개의 값이 각각 매칭되는 상황이기 때문에 가능했던 것이지, 절대로 Spread 구문 자체가 값이 아니다.

Spread 구문은 하나로 묶인 값을 여러 개의 값으로 펼친 개념이기 때문에

하나의 값으로 평가되는 것이 아니라 여러 값의 목록으로 평가된다.

 

만약에 

const number = [1];
coonst number = ...numbers

이와 같이 하나의 값을 가진 배열을 펼쳤다 하더라도

그냥 괄호가 벗겨지고 1이라는 하나의 값으로 평가되는 것이 아니라

아예 오류가 발생해버린다. 이 점을 주의해야한다.

 

또 하나를 살펴보면 아래와 같이 Spread 구문으로 배열을 펼친 다음에

중괄호로 감싸서 객체로 만들고 결과를 보면

const member = ["섭이", "쑹이", "섭섭"];
const newObj = { ...member };
console.log(newObj);

0번부터 시작하는 배열의 인덱스가 프로퍼티 네임이 되어서 객체가 만들어진다.


ES2015에서 Spread 구문이 등장했을 때 배열에서만 사용이 가능했고 일반 객체에선 사용할 수 없었다.

그러다 최근 ES2018에서도 일반 객체의 Spread 구문을 사용할 수 있는 표준이 등장했고

지금 대부분의 브라우저에서는 객체를 복사하거나

기존 객체를 가지고 새로운 객체를 만들 때 Spread 구문을 활용할 수 있다.

 

객체 Spread 하기

아래 코드를 살펴보면 중괄호안에서 객체를 Spread 하였고

const myName = {
  name: "SeopE",
};

const mymyName = {
  ...myName,
};

console.log(myName);
console.log(mymyName);

 

해당 객체의 프로퍼티들이 펼쳐지면서 객체를 복사할 수 있게 된다.

 

또한 아래와 같이 다른 객체가 가진 프로퍼티를 추가해서

새로운 객체를 만들 때 활용할 수 있다.

const latte = {
  esspresso: "30ml",
  milk: "150ml",
};

const cafeMocha = {
  ...latte,
  chocolate: "20ml",
};

console.log(latte);
console.log(cafeMocha);

 


그러나 Spread하면 새로윤 배열을 만들거나 함수의 아규먼트로 쓸 수 있었지만

객체로는 새로운 배열을 만들거나 함수의 아규먼트로 사용할 수는 없다.

const latte = {
  esspresso: "30ml",
  milk: "150ml",
};

const cafeMocha = {
  ...latte,
  chocolate: "20ml",
};

[...latte]; // iterable Error

(function (...args) {
  for (const arg of args) {
    console.log(arg);
  }
});(...cafeMocha) //SyntaxError Error

 

그렇기 때문에 객체를 Spread 할 때는 반드시 객체를 표현하는 중괄호 안에서 활용해야 한다.

 


▶ GitHub

https://github.com/SeopE9611/JavaScript_soloPlay/tree/main/Modern_JS/16.Spread%EA%B5%AC%EB%AC%B8

 

JavaScript_soloPlay/Modern_JS/16.Spread구문 at main · SeopE9611/JavaScript_soloPlay

Contribute to SeopE9611/JavaScript_soloPlay development by creating an account on GitHub.

github.com

 

▶ Notion

반응형