구조 분해 할당 파트 https://ko.javascript.info/destructuring-assignment
할당 할 값들 중 넘어가고 싶은 것은 빈 칸으로 둔다.
// 두 번째 요소는 필요하지 않음
let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert( title ); // Consul
할당 연산자 우측엔 배열뿐 아니라 모든 이터러블(반복 가능한 객체)이 올 수 있다.
즉, 구조 분해 할당을 적용할 수 있다.
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 메서드와 구조 분해 할당을 조합하면 객체의 키와 값을 순회해서 변수로 분해 할당할 수 있다.
Map 자료구조도 마찬가지다.
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 문법을 쓴다.
...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
할당 값을 저장할 변수 개수가 할당 값 배열의 길이보다 많아도 에러가 발생하지 않는다. 할당할 값이 변수 개수보다 부족하면 그 부족한 값은 에러 없이 undefined로 취급된다.
let [firstName, surname] = [];
alert(firstName); // undefined
alert(surname); // undefined
할당 값을 저장할 변수에 '=' 연산자를 이용하면 할당할 값이 없을 때 기본으로 할당해 줄 값인 기본값(default value)을 설정할 수 있다.
// 기본값
let [name = "Guest", surname = "Anonymous"] = ["Julius"];
alert(name); // Julius (배열에서 받아온 값)
alert(surname); // Anonymous (기본값)
기본값은 위처럼 string 형태 뿐만 아니라 표현식이나 함수를 설정할 수도 있다.
// name의 prompt만 실행됨
let [surname = prompt('성을 입력하세요.'), name = prompt('이름을 입력하세요.')] = ["김"];
alert(surname); // 김 (배열에서 받아온 값)
alert(name); // prompt에서 받아온 값
객체에도 구조 분해 할당 문법을 사용할 수 있다.
객체 내 프로퍼티 이름을 가져와 할당할 수 있는데 특이한 점은 콜론(:)을 이용해 프로퍼티와 같은 이름의 변수에 해당 프로퍼티 값을 할당하는 것이 아니라 다른 이름의 변수에 할당할 수도 있다.
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
객체 구조 분해 할당에도 배열의 구조 분해 할당과 같이 기본값을 지정할 수 있다.
기본값에는 마찬가지로 표현식과 함수도 올 수 있다.
let options = {
title: "Menu"
};
let {width = 100, height = 200, title} = options;
alert(title); // Menu
alert(width); // 100
alert(height); // 200
//--------------------------------------------------
let options = {
title: "Menu"
};
let {width = prompt("width?"), title = prompt("title?")} = options;
alert(title); // Menu
alert(width); // prompt 창에 입력한 값
많은 프로퍼티 중 원하는 값만 가져오는 것도 가능하다.
let options = {
title: "Menu",
width: 100,
height: 200
};
// title만 변수로 뽑아내기
let { title } = options;
alert(title); // Menu
기존에 존재하는 변수들에도 객체를 할당할 수 있는데 그냥 {}를 사용하면 단락을 나누는 코드 블록으로 인식되어 에러가 발생된다. 에러를 해결하려면 할당문을 괄호로 감싸 자바스크립트가 {}를 코드 블록이 아닌 표현식으로 해석되도록 하면 된다.
let title, width, height;
// SyntaxError: Unexpected token '=' 이라는 에러가 아랫줄에서 발생합니다.
{title, width, height} = {title: "Menu", width: 200, height: 100}; //(X)
//-------------------------------------------------------------------------
let title, width, height;
// 에러가 발생하지 않는다.
({title, width, height} = {title: "Menu", width: 200, height: 100}); //(O)
alert( title ); // Menu
프로퍼티 값으로 객체나 배열이 들어간 중첩 구조도 구조 분해가 가능하다.
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: w = 100, // width는 w에,
height: h = 200, // height는 h에,
items: [item1, item2] // items의 첫 번째 요소는 item1에, 두 번째 요소는 item2에 할당함
}) {
alert( `${title} ${w} ${h}` ); // My Menu 100 200
alert( item1 ); // Item1
alert( item2 ); // Item2
}
showMenu(options);
단, 함수 매개변수를 구조 분해할 땐 모든 인수에 기본값을 할당해 주려면 빈 객체를 명시적으로 전달해야하는 것을 주의해야 한다.
이 문제를 예방하기 위해서는 빈 객체 {}를 매개변수 전체의 기본값(default value)으로 만들면 된다.
showMenu({}); // 모든 인수에 기본값이 할당.
showMenu(); // 에러가 발생할 수 있다.
//-----------------------------------------------
function showMenu({ title = "Menu", width = 100, height = 200 } = {}) {
alert( `${title} ${width} ${height}` );
}
showMenu(); // Menu 100 200
이렇게 인수 객체의 기본값을 빈 객체 {}로 설정하면 어떤 경우든 분해할 것이 생겨서 함수에 인수를 하나도 전달하지 않아도 에러가 발생하지 않는다.