구조 분해 할당

양주영·2021년 8월 30일
0

javascript

목록 보기
15/42

키를 가진 데이터 여러 개를 하나의 엔티티에 저장할 땐 객체,
컬렉션에 데이터를 순서대로 저장할 땐 배열을 사용한다.

함수에 객체나 배열을 전달해야 하는 경우가 생기는데 객체나 배열이 저장된 데이터 전체가 아닌 일부만 필요할 경우가 생긴다. 이 때 객체나 배열을 변수로 ‘분해’할 수 있게 해주는 구조 분해 할당 (destructuring assignment) 을 사용할 수 있다.
이 외에도 함수의 매개변수가 많거나 매개변수 기본값이 필요한 경우 등에서 구조 분해(destructuring)를 사용한다.



📍 배열 분해하기


배열이 어떻게 변수로 분해되는지 알아보자.

// 이름과 성을 요소로 가진 배열
let arr = ["Bora", "Lee"]

// 구조 분해 할당을 이용해
// firstName엔 arr[0]을
// surname엔 arr[1]을 할당하였습니다.
let [firstName, surname] = arr;

alert(firstName); // Bora
alert(surname);  // Lee

인덱스를 이용해 배열에 접근하지 않고도 변수로 이름과 성을 사용할 수 있게 된다.
아래와 같이 split 같은 반환 값이 배열인 메서드를 함께 활용해도 좋다.

let [firstName, surname] = "Bora Lee".split(' ');


💡 '분해(destructuring)'는 '파괴(destructive)'를 의미하지 않습니다.

구조 분해 할당이란 명칭은 어떤 것을 복사한 이후에 변수로 '분해(destructurize)'해준다는 의미 때문에 붙여졌다. 이 과정에서 분해 대상은 수정 또는 파괴되지 않는다.

// let [firstName, surname] = arr;
let firstName = arr[0];
let surname = arr[1];

💡 쉼표를 사용하여 요소 무시하기

쉼표를 사용하면 필요하지 않은 배열 요소를 버릴 수 있다.

// 두 번째 요소는 필요하지 않음
let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

alert( title ); // Consul

두 번째 요소는 생략되었지만, 세 번째 요소는 title이라는 변수에 할당된 것을 확인할 수 있다.
할당할 변수가 없기 때문에 네 번째 요소 역시 생략됨.


💡 할당 연산자 우측엔 모든 이터러블이 올 수 있다.

배열뿐만 아니라 모든 이터러블(iterable, 반복 가능한 객체)에 구조 분해 할당을 적용할 수 있다.

let [a, b, c] = "abc"; // ["a", "b", "c"]
let [one, two, three] = new Set([1, 2, 3]);



💡 할당 연산자 좌측엔 뭐든지 올 수 있다.

할당 연산자 좌측엔 ‘할당할 수 있는(assignables)’ 것이라면 어떤 것이든 올 수 있다.
아래와 같이 객체 프로퍼티도 가능하다.

let user = {};
[user.name, user.surname] = "Bora Lee".split(' ');

alert(user.name); // Bora



💡 .entries()로 반복하기

이 메서드와 구조 분해를 조합하면 객체의 키와 값을 순회해 변수로 분해 할당할 수 있다.

let user = {
  name: "John",
  age: 30
};

// 객체의 키와 값 순회하기
for (let [key, value] of Object.entries(user)) {
  alert(`${key}:${value}`); // name:John, age:30이 차례대로 출력
}

맵에도 물론 이 메서드를 활용할 수 있다.

let user = new Map();
user.set("name", "John");
user.set("age", "30");

for (let [key, value] of user) {
  alert(`${key}:${value}`); // name:John, then age:30
}



💡 변수 교환 트릭

두 변수에 저장된 값을 교환할 때 구조 분해 할당을 사용할 수 있다.

let guest = "Jane";
let admin = "Pete";

// 변수 guest엔 Pete, 변수 admin엔 Jane이 저장되도록 값을 교환함
[guest, admin] = [admin, guest];

alert(`${guest} ${admin}`); // Pete Jane(값 교환이 성공적으로 이뤄졌습니다!)

임시 배열을 만들어 두 변수를 담고, 요소 순서를 교체해 배열을 분해하는 방식을 사용했다. 두 개뿐만 아니라 그 이상의 변수에 담긴 값도 교환 가능하다.



- ‘…’로 나머지 요소 가져오기

배열 앞쪽에 위치한 값 몇 개만 필요하고 그 이후 이어지는 나머지 값들은 한데 모아서 저장하고 싶을 때.
이럴 때는 점 세 개 ...를 붙인 매개변수 하나를 추가하면 ‘나머지(rest)’ 요소를 가져올 수 있다.

let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

alert(name1); // Julius
alert(name2); // Caesar

// `rest`는 배열입니다.
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2

rest는 나머지 배열 요소들이 저장된 새로운 배열이 된다. rest 대신에 다른 이름을 사용해도 되는데, 변수 앞의 점 세 개(...)와 변수가 가장 마지막에 위치해야 한다는 점은 잊지 말자.



- 기본값

할당하고자 하는 변수의 개수가 분해하고자 하는 배열의 길이보다 크더라도 에러가 발생하지 않는다. 할당할 값이 없으면 undefined로 취급되기 때문이다.

let [firstName, surname] = [];

alert(firstName); // undefined
alert(surname); // undefined

=을 이용하면 할당할 값이 없을 때 기본으로 할당해 줄 값인 '기본값(default value)'을 설정할 수 있다.

// 기본값
let [name = "Guest", surname = "Anonymous"] = ["Julius"];

alert(name);    // Julius (배열에서 받아온 값)
alert(surname); // Anonymous (기본값)

복잡한 표현식이나 함수 호출도 기본값이 될 수 있다. 이렇게 기본식으로 표현식이나 함수를 설정하면 할당할 값이 없을 때 표현식이 평가되거나 함수가 호출된다.
아래 예시에선 값이 제공되지 않았을 때만 함수가 호출되므로, prompt는 한 번만 호출된다.

// name의 prompt만 실행됨
let [surname = prompt('성을 입력하세요.'), name = prompt('이름을 입력하세요.')] = ["김"];

alert(surname); // 김 (배열에서 받아온 값)
alert(name);    // prompt에서 받아온 값


📍 객체 분해하기


구조 분해 할당으로 객체도 분해할 수 있다.

문법 :

let {var1, var2} = {var1:, var2:}
//할당 연산자 우축엔 분해하고자 하는 객체를, 좌측엔 상응하는 객체 프로퍼티의 '패턴'을 넣는다. 
let options = {
  title: "Menu",
  width: 100,
  height: 200
};

let {title, width, height} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200

프로퍼티 options.titleoptions.width, options.height에 저장된 값이 상응하는 변수에 할당됐다. 순서는 바뀌어도 좋다.

let options = {
  title: "Menu",
  width: 100,
  height: 200
};


// { 객체 프로퍼티: 목표 변수 }
let {width: w, height: h, title} = options;

// width -> w
// height -> h
// title -> title

alert(title);  // Menu
alert(w);      // 100
alert(h);      // 200


- 나머지 패턴 ‘…’

분해하려는 객체의 프로퍼티 개수가 할당하려는 변수의 개수보다 많다면 '나머지’를 어딘가에 할당하면 된다.

나머지 패턴(rest pattern)을 사용하면 배열에서 했던 것처럼 나머지 프로퍼티를 어딘가에 할당하는 게 가능하다.

let options = {
  title: "Menu",
  height: 200,
  width: 100
};

// title = 이름이 title인 프로퍼티
// rest = 나머지 프로퍼티들
let {title, ...rest} = options;

// title엔 "Menu", rest엔 {height: 200, width: 100}이 할당됩니다.
alert(rest.height);  // 200
alert(rest.width);   // 100


📍 중첩 구조 분해


객체나 배열이 다른 객체나 배열을 포함하는 경우, 좀 더 복잡한 패턴을 사용하면 중첩 배열이나 객체의 정보를 추출할 수 있다. 이를 중첩 구조 분해(nested destructuring)라고 한다.
아래 예시에서 객체 options의 size 프로퍼티 값은 또 다른 객체이다. items 프로퍼티는 배열을 값으로 가지고 있다. 대입 연산자 좌측의 패턴은 정보를 추출하려는 객체 options와 같은 구조를 갖추고 있다.

let options = {
  size: {
    width: 100,
    height: 200
  },
  items: ["Cake", "Donut"],
  extra: true
};

// 코드를 여러 줄에 걸쳐 작성해 의도하는 바를 명확히 드러냄
let {
  size: { // size는 여기,
    width,
    height
  },
  items: [item1, item2], // items는 여기에 할당함
  title = "Menu" // 분해하려는 객체에 title 프로퍼티가 없으므로 기본값을 사용함
} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200
alert(item1);  // Cake
alert(item2);  // Donut


📍 똑똑한 함수 매개변수


매개변수 모두를 객체에 모아 함수에 전달해, 함수가 전달받은 객체를 분해하여 변수에 할당하고 원하는 작업을 수행할 수 있도록 하자.

// 함수에 전달할 객체
let options = {
  title: "My menu",
  items: ["Item1", "Item2"]
};

// 똑똑한 함수는 전달받은 객체를 분해해 변수에 즉시 할당함
function showMenu({title = "Untitled", width = 200, height = 100, items = []}) {
  // title, items – 객체 options에서 가져옴
  // width, height – 기본값
  alert( `${title} ${width} ${height}` ); // My Menu 200 100
  alert( items ); // Item1, Item2
}

showMenu(options);

이렇게 똑똑한 함수 매개변수 문법은 구조 분해 할당 문법과 동일합니다.

function({
  incomingProperty: varName = defaultValue
  ...
})

매개변수로 전달된 객체의 프로퍼티 incomingPropertyvarName에 할당되고, 만약 값이 없다면 defaultValue가 기본값으로 사용된다.

참고로 이렇게 함수 매개변수를 구조 분해할 땐, 반드시 인수가 전달된다고 가정되고 사용된다는 점에 유의해야 한다. 모든 인수에 기본값을 할당해 주려면 빈 객체를 명시적으로 전달해야 한다.




참조 : https://ko.javascript.info/destructuring-assignment

profile
뚜벅뚜벅

0개의 댓글