const flower = {
name: 'Rose',
color: 'Red'
};
const name = flower.name;
const color = flower.color;
console.log(name); // 'Rose'
console.log(color); // 'Red'
flower.name 값을 name 변수에 넣고, flower.color 값을 color 변수에 넣습니다.
하지만 위와 같이 값을 대입하면 반복되는 부분이 발생합니다. 바로 ‘name’과 ‘color’입니다.
대입 과정에서 name이 변수 선언에 한 번, 그리고 flower 객체의 속성 접근에 한 번, 총 두 번이 사용됩니다.
color도 마찬가지입니다.
비구조화 할당은 이런 번거로움을 없애고자 할 때 사용합니다.
비구조화 할당을 사용하면 객체에서 속성을 가져와 같은 이름의 변수에 대입할 때 속성명을 한번 더 명시할 필요가 없습니다.
게다가 속성이 여러 개일지라도 한번의 선언으로 해결이 가능합니다.
아래 코드에서는 위 코드를 리팩토링하여 비구조화 할당을 사용합니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const { name, color } = flower;
console.log(name); // 'Rose'
console.log(color); // 'Red'
‘const { name, color } = flower’가 바로 객체 비구조화입니다.
이 구문으로 name과 color 변수를 선언하고, flower.name과 flower.color 속성의 값을 같은 이름 변수에 할당합니다.
다음은 객체의 속성값에 접근하는 두 가지 방법입니다.
const name = flower.name;
const color = flower.color;
// 위와 아래는 같은 결과
const { name, color } = flower;
속성명과 변수명이 중복되지 않으므로 비구조화가 훨씬 깔끔하고 편리한 것을 알 수 있습니다.
–
2. 속성값 가져오기
객체 비구조화의 기본 문법은 간단합니다.
const { identifier } = expression;
여기서 identifier는 속성에 접근할 이름이고, expression은 identifier가 접근하는 객체입니다.
비구조화를 하면 identifier 변수는 접근한 속성값을 갖게 됩니다.
위와 같은 코드이지만 속성 접근자를 사용하게 되면 다음과 같습니다.
const identifier = expression.identifier;
위 내용을 토대로 비구조화 할당을 연습해 보겠습니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const { name } = flower;
console.log(name); // 'Rose'
‘const { name } = flower;’는 name 변수를 선언하고, flower.name의 속성값을 대입하는 비구조화 할당입니다.
–
3. 여러 속성값 한번에 가져오기
여러 속성값을 가진 객체의 비구조화는 쉼표를 사용하면 됩니다.
const { identifier1, identifier2, ..., identifierN } = expression;
여기서 identifier1, identifier2, …, identifierN은 속성에 접근할 이름이고, expression은 identifier가 접근하는 객체입니다. 비구조화를 하면 각 identifier 변수는 접근한 속성값을 갖게 됩니다.
속성 접근자를 사용하는 코드는 다음과 같습니다.
const identifier1 = expression.identifier1;
const identifier2 = expression.identifier2;
// ......
const identifierN = expression.identifierN;
그럼 두 개의 속성값을 할당하는 첫 번째 샘플 코드를 다시 확인해 보겠습니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const { name, color } = flower;
console.log(name); // 'Rose'
console.log(color); // 'Red'
‘const { name, color } = flower;’는 name, color 두 변수를 생성하고, 각각 flower.name과 flower.color의 속성값을 할당합니다.
–
4. 기본값 설정하기
비구조화를 하더라도 객체에 동일한 속성명이 존재하지 않는 경우 undefined가 할당됩니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const { meaning } = flower;
console.log(meaning); // undefined
위와 같이 속성이 존재하지 않는 경우 기본값 설정이 가능하며, 문법은 다음과 같습니다.
const { identifier = defaultValue } = expression;
identifier가 expression 객체의 속성에 접근하는 이름이 됩니다. expression 객체 내 identifier 속성이 존재하지 않으면 지정한 기본값인 defaultValue가 대입됩니다.
다음 코드와 같은 기능을 합니다.
const identifier = expression.identifier === undefined ? defaultValue : expression.identifier;
기본값 설정 옵션을 더해 코드를 수정해 보겠습니다.
const flower = {
name: 'Rose',
color: 'Red'
}
const { meaning = 'love' } = flower;
console.log(meaning) // 'love'
undefined 대신 ‘love’가 대입됩니다.
–
5. 별명(alias) 정하기
객체의 속성명과 다른 이름으로 변수를 선언하고 싶을 때는 별명을 지정하면 됩니다.
const { identifier: aliasIdentifier } = expression;
여기서 identifier는 속성에 접근하는 이름이며, aliasIdentifier는 변수로 사용할 이름입니다. 비구조화를 하면 aliasIdentifier가 속성값을 갖습니다.
다음 코드와 같은 의미입니다.
const aliasIdentifier = expression.identifier;
실제 별명을 적용한 코드는 다음과 같습니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const { color: realColor } = flower;
console.log(realColor); // 'Red'
console.log(color); // 에러 발생(color is not defined)
위 코드는 realColor로 변수를 선언하고, flower.color값을 할당하여 비구조화를 진행합니다.
–
6. 내부 객체의 속성값 가져오기
앞에서 확인한 샘플은 원시형 데이터 타입(String, Number 등)의 속성을 갖는 일반 객체입니다.
그러나 일부는 객체 안에 또 다른 객체를 갖습니다. 물론 이러한 형태를 가진 객체도 비구조화 할당이 가능합니다.
const { nestedObject: { identifier } } = expression;
nestedObject는 내부 객체명이고, identifier는 내부 객체의 속성명입니다.
비구조화 할당을 통해 identifier가 내부 객체의 속성값을 가지며, 다음 코드와 같은 의미입니다.
const identifier = expression.nestedObject.identifier;
내부 객체의 깊이는 제한이 없으며, 중괄호{ }만 추가해주면 됩니다.
const { propA: { propB: { propC: {......} } } } = object;
다음 샘플을 통해 내부 객체에 접근하여 비구조화 할당을 진행하는 코드를 확인해 보겠습니다.
const flower = {
name: 'Rose',
color: 'Red',
blooming: {
season: 'spring'
}
};
//Object destructuring
const { blooming: { season } } = flower;
console.log(season) // 'spring'
‘const { blooming: { season } } = flower;’는 내부 객체 blooming의 season 속성값을 할당합니다.
–
7. 동적 이름으로 속성값 가져오기
동적 이름(Dynamic Name)의 사용도 가능합니다.
const { [propName]: identifier } = expression;
propName은 속성명(주로 string 타입)이며, identifier는 값이 할당될 변수의 이름입니다.
다음 코드와 같은 의미를 갖습니다.
const identifier = expression[propName];
다음 샘플을 통해 속성명으로 사용되는 prop을 확인하겠습니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const prop = 'name';
const { [prop]: flowerName } = expression;
console.log(flowerName); // 'Rose'
‘const { [prop]: flowerName } = expression’에서 flowerName 변수에 flower[prop] 속성값을 할당하며, prop은 접근할 속성명을 가진 변수입니다.
–
8. 비구조화 할당 후 남겨진 객체
나머지 데이터를 관리하는 문법은 비구조화 할당에서 유용하게 사용할 수 있습니다.
const { identifier, ...rest } = expression;
위 코드에서 identifier를 제외한 나머지 속성은 rest 변수에 할당됩니다.
아래 코드에서 name 속성을 제외한 나머지 속성을 정리하는 샘플을 확인해 보겠습니다.
const flower = {
name: 'Rose',
color: 'Red'
};
const { name, ...realColor } = flower;
console.log(realColor) // { realColor: 'Red' }
name 속성값을 할당한 뒤 나머지 속성들은 realColor 변수에 할당합니다.
–
9. 자주 사용되는 구문
앞에서 확인한대로 비구조화는 속성값을 변수에 할당합니다.
변수 타입은 const, let, var 모두 사용이 가능하며, 이미 선언된 변수에도 할당이 가능합니다.
let을 사용한 방법은 다음과 같습니다.
//let
const flower = {
name: 'Rose',
};
let { name } = flower;
console.log(name); // 'Rose'
var를 사용한 방법은 다음과 같습니다.
//var
const flower = {
name: 'Rose',
};
var { name } = flower;
console.log(name); // 'Rose'
이미 선언된 변수에 할당하는 방법은 다음과 같습니다.
//existing variable
let name;
const flower = {
name: 'Rose',
};
({ name } = flower);
console.log(name); // 'Rose'
for…of 반복문을 사용한 비구조화 할당은 다음과 같습니다.
const flowers = [
{ name: 'Rose' },
{ name: 'Lily' }
];
for (const { name } of flowers) {
console.log(name) //'Rose', 'Lily'
}
사실 비구조화는 할당이 가능한 곳이면 어디든지 사용이 가능하다고 볼 수 있습니다.
예를 들면 다음과 같이 함수 파라미터의 비구조화도 가능합니다.
const flowers = [
{ name: 'Rose' },
{ name: 'Lily' }
];
const names = flowers.map(
function({ name }) {
return name;
}
)
console.log(names); // ['Rose', 'Lily']
‘function({ name })’은 함수의 파라미터를 비구조화하여, name 변수에 name 속성을 할당합니다.
10. 변수 값 서로 교환(swap)
비구조화 할당을 사용하면 두 변수의 값을 편리하게 교환할 수도 있으며, 기존처럼 데이터를 임시로 보관할 변수가 필요하지 않습니다.
let a = 1;
let b = 2;
//기존 교환 방법
const temp = a;
a = b;
b = temp;
//비구조화를 통한 교환
[a, b] = [b, a];