[JS] spread 연산자

Minyoung's Conference·2022년 6월 13일
0

JavaScript

목록 보기
12/28
post-thumbnail

spread연산자에 대해 배워보자.

우선 쿠키들을 좀 만들어볼까나?

const cookie = {
  base: "cookie",
  madeIn: "korea"
};

const chocochipCookie = {
  base: "cookie",
  madeIn: "korea",
  toping: "chocochip"
};

const blueberryCookie = {
  base: "cookie",
  madeIn: "korea",
  toping: "blueberry"
};

const strawberryCookie = {
  base: "cookie",
  madeIn: "korea",
  toping: "strawberry"
};

벌써 반복되는 것들이 눈에 들어온다... ( base, madeIn..)
이렇게 반복되는 것들을 없애기 위해 spread연산자를 사용해주면 좋다.
cookie라는 상수는 모든 다른 종류의 쿠키에 공통적으로 들어가게 된다.

const cookie = {
  base: "cookie",
  madeIn: "korea"
};

const chocochipCookie = {
  ...cookie,
  toping: "chocochip"
};

const blueberryCookie = {
  ...cookie,
  toping: "blueberry"
};

const strawberryCookie = {
  ...cookie,
  toping: "strawberry"
};

console.log(chocochipCookie);
console.log(blueberryCookie);
console.log(strawberryCookie);

이렇게 써도 chocochipCookie를 불러왔을 때, base, madeIn 결과를 받아낼 수 있다.

그럼 배열이 빠지면 섭하다. 배열에서도 확인해보자.

const notopingCookie = ["촉촉쿠키", "꾸덕쿠키"];
const topingCookie = ["바나나쿠키", "딸기쿠키", "블루베리쿠키", "초코쿠키"];

이 배열들을 합쳐주기 위해선 concat 메소드를 사용했지만, spread연산자를 사용하면 더 쉽게 합칠 수 있다.

const notopingCookie = ["촉촉쿠키", "꾸덕쿠키"];
const topingCookie = ["바나나쿠키", "딸기쿠키", "블루베리쿠키", "초코쿠키"];

const allCookies = [...notopingCookie, ...topingCookie];

console.log(allCookies); // (6) ["촉촉쿠키", "꾸덕쿠키", "바나나쿠키", "딸기쿠키", "블루베리쿠키", "초코쿠키"]

배열에서도 객체의 프로퍼티를 펼치는 것처럼 배열의 원소를 순서대로 펼칠 수 있다. 그리고 concat 메소드와 달리 중간에 요소를 추가할 수도 있다.

const allCookies = [...notopingCookie, "추가쿠키",  ...topingCookie];

console.log(allCookies); // (6) ["촉촉쿠키", "꾸덕쿠키", "추가쿠키", "바나나쿠키", "딸기쿠키", "블루베리쿠키", "초코쿠키"]

전개연산자의 동작 원리에 대해 알아보자

- 배열의 요소나 객체를 나열해주는 연산자
- 배열이나 객체의 복사본(원본 영향x)을 만들 수 있고, 여러 개의 배열이나 객체를 손쉽게 병합가능
- 또한, 함수의 매개변수나 인자값으로도 사용 가능

**전개연산자의 내부 동작을 알아보자.** 
전개연산자가 호출되면 "iterator-looping" 이라는 액션을 수행한다.
어떤 객체에 [Symbol.iterator] 프로퍼티가 존재한다면 이터러블하고 반복문을 돌릴 수 있다.
(모든 자바스크립트 객체는 반복이라는 동작을 하기 위해 위 프로퍼티가 필요하다.)

const b = [1,2,3];
const a = [...b];

다음과 같은 작업을 수행하면 내부에서는 아래와 같은 동작이 발생한다.

if (!(Typeof(b) is Iterable)) {
  throw TypeError
}
var a = [];
for (var i = 0; i < b.length; i += 1) {
  a.push(b[i]);
}

위 과정이 이터러블 객체에 대한 복사인데, 객체가 이터러블임이 확인이되면 
for-loop 과 같은 단순한 반복문을 통해 모든 요소를 하나씩 옮겨 담는다. 
여기서 중요한 점은, 옮겨 담는 요소의 깊이(depth)는 철저히 1-dpt 라는 것. 
전개 연산자 역시 이와 같은 이유로 중첩 구조를 복사하지 못한다.

**배열 복사**

let numArr = [1, 2, 3, 4, 5, 6];
let copyNumArr = [...numArr];

console.log(numArr, copyNumArr); // [ 1, 2, 3, 4, 5, 6 ] [ 1, 2, 3, 4, 5, 6 ]

console.log(numArr === copyNumArr); // false (다른 주소값을 가짐)

**배열 병합**

let leftArr = [1, 2, 3, 4, 5];
let rightArr = [6, 7, 8, 9, 10];
let mergeArr = [...leftArr, ...rightArr];
console.log(mergeArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

* push() 사용
let leftArr = [1, 2, 3, 4, 5];
let rightArr = [6, 7, 8, 9, 10];
leftArr.push(...rightArr);
console.log(leftArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

**배열 중간값 병합**

let leftArr = [1, 2, 3, 4, 5];
let rightArr = [6, 7, ...leftArr, 8, 9, 10]; // 중간에 전개 연산자를 이용한 배열 삽입
console.log(rightArr); // [6, 7, 1, 2, 3, 4, 5, 8, 9, 10]

**함수의 인자값으로 전개연산자 사용**

let sum = function(a, b, c){
	return a+b+c;
}

let arr = [1,10,100];

console.log(sum(arr[0], arr[1], arr[2])); // 111
console.log(sum(...arr)); // 111

**함수의 매개변수로 전개연산자 사용**

let sum = function(...arr){
	let result = 0;
	for(i of [...arr]){
		result += i;
	}
	return result;
}

console.log(sum(1, 100, 1000, 100000)); // 101101
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); // 55

**가변 매개변수도 포함한다면**

let sum = function(a, ...arr){
	let result = 0;
	for(i of [...arr]){
		console.log(i);
		result += i;
	}
	return a * result;
}

console.log(sum(5, 100, 1000, 100000)); // 505500
console.log(sum(10,2,3,4,5,6,7,8,9,10)); // 540

**객체 복사**

let Person = {
	name : "ludeno",
	from : "Korea",
	language : "Javascript"
};

let anotherPerson = {...Person};

console.log(Person); 
// { name: 'ludeno', from: 'Korea', language: 'Javascript' }
console.log(anotherPerson); 
// { name: 'ludeno', from: 'Korea', language: 'Javascript' }
console.log(Person === anotherPerson); 
// false (주소값이 다름, 다른 객체)

let Person = {
	name : "ludeno",
	from : "Korea",
	language : "Javascript"
};
let clone = {
	...Person,
	butHeIs : "Clone"
};
console.log(clone);
// { name: 'ludeno', from: 'Korea', language: 'Javascript', butHeIs: 'Clone' }

**객체 병합**

let Person = {
	name : "ludeno",
	language : "Javascript"
}
let Korean = {
	from : "Korea",
	UsedIDE : "Vscode"
}

let mergeObj = {...Person, ...Korean};

console.log(mergeObj);
// {
  name: 'ludeno',
  language: 'Javascript',
  from: 'Korea',
  UsedIDE: 'Vscode'
}

참조에 의한 객체 복사

(모단 자바스크립트 튜토리얼 참조)
객체는 참조에 의해 할당되고 복사된다. 변수엔 ‘객체’ 자체가 아닌 메모리상의 주소인 '참조’가 저장된다. 따라서 객체가 할당된 변수를 복사하거나 함수의 인자로 넘길 땐 객체가 아닌 객체의 참조가 복사된다.

그리고 복사된 참조를 이용한 모든 작업(프로퍼티 추가·삭제 등)은 동일한 객체를 대상으로 이뤄진다.

객체의 '진짜 복사본’을 만들려면 '얕은 복사(shallow copy)'를 가능하게 해주는 Object.assign이나 '깊은 복사’를 가능하게 해주는 _.cloneDeep(obj)를 사용하면 된다. 이때 얕은 복사본은 중첩 객체를 처리하지 못한다는 점을 기억해야 한다.

profile
안녕하세요, FE 개발자 김민영입니다.

0개의 댓글