모던 JavaScript 튜토리얼을 따라가면서 정리합니다.
함수에 객체나 배열을 전달해야 하는 경우가 생기곤 한다. 가끔 객체나 배열에 저장된 데이터 전체가 아닌 일부만 필요한 경우가 있다. 또한 함수에 매개변수가 많거나 매개변수 기본값이 필요한 경우도 있다. 이럴 때 구조 분해 할당을 사용한다.
구조 분해 할당을 사용하면 객체나 배열을 변수로 ‘분해’할 수 있다.
구조 분해 할당은 어떤 것을 복사한 이후에 변수로 분해(destructurize)해준다. 분해 대상은 수정 또는 파괴되지 않는다.
직접 변수에 할당하는 것보다 코드 양이 줄어든다는 점만 다르다.
배열 분해하기
1
let [item1 = default, item2, ...rest] = array;
array
의 첫 번째 요소는item1
에, 두 번째 요소는 변수item2
에 할당되고, 이어지는 나머지 요소들은 배열rest
에 저장된다....
로 나머지 요소를 가져올 수 있다. 배열 앞쪽에 위치한 값 몇 개만 필요하고 그 이후 이어지는 나머지 값들은 한 데 모아서 저장하고 싶을 때 사용한다.rest
는 할당한 나머지 값들이 저장된 새로운 배열이 된다.=
를 사용하면 할당할 값이 없을 때 기본으로 할당해줄 값인 ‘기본 값(default value)’을 설정할 수 있다. 복잡한 표현식이나 함수 호출도 기본값이 될 수 있다.1 2 3
let arr = ["Bora", "Lee"] let [firstName, surname] = arr
1
let [firstName, surname] = "Monica Kim".split(" ");
쉼표를 사용하면 필요하지 않은 배열 요소를 버릴 수 있다.
1 2 3
let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"]; alert(title); // Consul
할당할 변수가 없으면 버린다.
배열뿐만 아니라 모든 이터러블에 구조분해할당이 적용될 수 있다.
한편 할당연산자 좌측에는 ‘할당할 수 있는(assignable)’ 것이라면 어떤 것이든 올 수 있다. (객체 프로퍼티도 가능!)
Object.entries()
와 구조분해를 조합하면 객체의 키와 값을 순회해 변수로 분해 할당할 수 있다. 맵에도 이 메서드를 활용할 수 있다.1 2 3 4 5 6 7 8
let user = { name: "John", age: 30 }; for (let [key, value] of Object.entries(user)) alert(`${key}:${value}`); //name:John age:30
두 변수에 저장된 값을 교환할 때 구조 분해 할당을 사용할 수 있다. 예시에서는 임시 배열을 만들어 두 변수를 담고, 요소 순서를 교체해 배열을 분해하는 방식을 사용했다.
1 2 3 4 5
let guest = "Jane"; let admin = "Pete"; // 변수 guest엔 Pete, 변수 admin엔 Jane이 저장된다. [guest, admin] = [admin, guest];
객체 분해하기
1
let {prop : varName = default, ...rest} = object
object의 프로퍼티
prop
의 값은 변수varName
에 할당되는데,object
에prop
이 없으면default
가varName
에 할당된다. 연결한 변수가 없는 나머지 프로퍼티들은 객체rest
에 복사된다.할당 연산자 우측에는 분해하고자 하는 객체를, 좌측에는 상응하는 객체 프로퍼티의 패턴을 넣는다.
1 2 3 4 5 6 7
let options = { title: "Menu", width: 100, height: 200 }; let {title, width, height} = options;
순서는 중요하지 않다.
할당하는 연산자 좌측에는 더 복잡한 패턴이 올 수 있다. 분해하려는 객체의 프로퍼티와 변수의 연결을 원하는 대로 조정할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12
let options = { title: "Menu", width: 100, height: 200 }; // { 객체 프로퍼티: 목표 변수 } let {width: w, hegiht:h, title} = options; alert(title); //Menu alert(w); //100 alert(h); //200
프로퍼티가 많은 복잡한 객체에서 원하는 정보만 뽑아오는 것도 가능하다.
1
let { title } = options;
할당 연산자 좌측의 패턴과 우측의 구조가 같으면 중첩 배열이나 객체가 있는 복잡한 구조에서도 원하는 데이터를 뽑아낼 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
let options = { size: { width: 100, height: 200 }, items: ["Cake", "Donut"], extra: true }; let { size: { width, height }, items: [item1, item2], title: = "Menu" } = options;
똑똑한 함수 매개변수
매개변수에 기본값이 설정되어 있어 굳이 인수를 넘겨주지 않아도 되는 경우에 문제가 발생한다. 구조분해는 이럴 때 구세주가 된다. 매개변수 모두를 객체에 모아 함수에 전달해, 함수가 전달받은 객체를 분해하여 변수에 할당하고 원하는 작업을 수행할 수 있도록 만들 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
let options = { title: "My menu", items: ["Item1", "Item2"] }; function showMenu({ title="Untitled", width: w = 100, height: h = 200, items=[item1, item2]}) { alert( `${title} ${w} ${h}` ); // My Menu 100 200 alert( item1 ); // Item1 alert( item2 ); // Item2 } showMenu(options);
과제
구조분해할당
아래와 같은 객체가 있다고 가정해봅시다.
1
2
3
4
let user = {
name: "John",
years: 30
};
구조 분해 할당을 사용해 아래 미션을 수행해 보세요.
name
프로퍼티의 값을 변수name
에 할당하세요.years
프로퍼티의 값을 변수age
에 할당하세요.isAdmin
프로퍼티의 값을 변수isAdmin
에 할당하세요.isAdmin
이라는 프로퍼티가 없으면 false를 할당하세요.
미션을 달성하면 아래 예시를 제대로 실행할 수 있게 됩니다.
답
1
let {name, years: age, isAdmin = false} = user;
최대 급여 계산하기
급여 관련 정보가 저장된 객체 salaries
가 있다고 가정해 봅시다.
1
2
3
4
5
let salaries = {
"John": 100,
"Pete": 300,
"Mary": 250
};
가장 많은 급여를 받는 사람의 이름을 반환해주는 함수 topSalary(salaries)
를 만들어봅시다. 조건은 아래와 같습니다.
salaries
가 비어있으면 함수는null
을 반환해야 합니다.- 최대 급여를 받는 사람이 여러 명이라면 그 중 아무나 한 명 반환하면 됩니다.
답
1
2
3
4
5
6
7
8
9
10
11
12
function topSalary(salaries) {
if (salaries == null) return null;
let maxValue = 0;
let maxKey = null;
for (let [name, salary] of Object.entries(salaries)) {
if (maxValue < salary) {
maxValue = salary;
maxKey = name;
}
}
return maxKey;
}