구조 분해 할당(destructuring)

Cho Dragoo·2021년 6월 1일
0
post-thumbnail

"모던 자바스크립트 Deep Dive" 라는 책을 보고
JS 이론중에서 개인적으로 부족한 개념을 복습하며 기록한 글입니다.

구조 분해 할당(destructuring)은 구조화된 배열과 같은 이터러블 또는 객체를 분해하여
1개 이상의 변수에 개별적으로 할당하는 것이다.
마치 여러가지 기록되어있는 하나의 서류에서 필요한 문서만 골라 복사해 활용하는것과 비슷하다.


배열 디스트럭처링 할당


ES5에서 할당하는 방법

// ES5
var arr = [1, 2, 3];

var one   = arr[0];
var two   = arr[1];
var three = arr[2];

console.log(one, two, three); // 1 2 3

ES6 이후 할당하는 방법

const arr = [1, 2, 3];

// ES6 배열 디스트럭처링 할당
// 변수 one, two, three를 선언하고 배열 arr을 디스트럭처링하여 할당한다.
// 이때 할당 기준은 배열의 인덱스다.
const [one, two, three] = arr;

console.log(one, two, three); // 1 2 3
const [x, y]; // SyntaxError: Missing initializer in destructuring declaration

const [a, b] = {}; // TypeError: {} is not iterable

만약 우변에 이터러블을 할당하지 않으면 에러가 발생한다.



const [a, b] = [1, 2];
console.log(a, b); // 1 2

const [c, d] = [1];
console.log(c, d); // 1 undefined

const [e, f] = [1, 2, 3];
console.log(e, f); // 1 2

const [g, , h] = [1, 2, 3];
console.log(g, h); // 1 3

배열 디스트럭처링 할당의 기준은 배열의 인덱스다. 즉 순서대로 할당되며 변수의 개수와 이터러블의 요소 개수가 반드시 일치할 필요는 없다.



// 기본값
const [a, b, c = 3] = [1, 2];
console.log(a, b, c); // 1 2 3

// 기본값보다 할당된 값이 우선한다.
const [e, f = 10, g = 3] = [1, 2];
console.log(e, f, g); // 1 2 3

변수에 기본값도 설정이 가능



다음예제는 url을 파싱하여 protocol, host, path 프로퍼티를 갖는 객체를 생성해 반환한다.

// url을 파싱하여 protocol, host, path 프로퍼티를 갖는 객체를 생성해 반환한다.
function parseURL(url = '') {
  // '://' 앞의 문자열(protocol)과 '/' 이전의 '/'으로 시작하지 않는 문자열(host)과 '/' 이후의 문자열(path)을 검색한다.
  const parsedURL = url.match(/^(\w+):\/\/([^/]+)\/(.*)$/);
  console.log(parsedURL);
  /*
  [
    'https://developer.mozilla.org/ko/docs/Web/JavaScript',
    'https',
    'developer.mozilla.org',
    'ko/docs/Web/JavaScript',
    index: 0,
    input: 'https://developer.mozilla.org/ko/docs/Web/JavaScript',
    groups: undefined
  ]
  */

  if (!parsedURL) return {};

  // 배열 디스트럭처링 할당을 사용하여 이터러블에서 필요한 요소만 추출한다.
  const [, protocol, host, path] = parsedURL;
  return { protocol, host, path };
}

const parsedURL = parseURL('https://developer.mozilla.org/ko/docs/Web/JavaScript');
console.log(parsedURL);
/*
{
  protocol: 'https',
  host: 'developer.mozilla.org',
  path: 'ko/docs/Web/JavaScript'
}
*/

// Rest 요소
const [x, ...y] = [1, 2, 3];
console.log(x, y); // 1 [ 2, 3 ]

Rest 파라미터와 유사하게 Rest요소 ...를 쓸 수있다.



겍체 디스트럭처링 할당

ES5에서 할당하는 방법

ES5에선 user.firstName처럼 프로퍼티를 사용 했어야했다.

// ES5
var user = { firstName: 'Ungmo', lastName: 'Lee' };

var firstName = user.firstName;
var lastName  = user.lastName;

console.log(firstName, lastName); // Ungmo Lee


ES6에서 할당기준이 프로퍼티 키라서 순서의 의미가 없다

const user = { firstName: 'Ungmo', lastName: 'Lee' };

// ES6 객체 디스트럭처링 할당
// 변수 lastName, firstName을 선언하고 user 객체를 디스트럭처링하여 할당한다.
// 이때 프로퍼티 키를 기준으로 디스트럭처링 할당이 이루어진다. 순서는 의미가 없다.
const { lastName, firstName } = user;

console.log(firstName, lastName); // Ungmo Lee


객체 디스트럭처링 할당을 위해서 좌변에 변수를 선언한다. 이때 변수는 겍체리터널 형태로 선언.

const { lastName, firstName } = { firstName: 'Ungmo', lastName: 'Lee' };


우변에 겍체로 평가되는 표현식을 할당안하면 에러가 발생

const { lastName, firstName };
// SyntaxError: Missing initializer in destructuring declaration

const { lastName, firstName } = null;
// TypeError: Cannot destructure property 'lastName' of 'null' as it is null.


프로퍼티 축약 표현이 가능하다

const { lastName, firstName } = user;
// 위와 아래는 동치다.
const { lastName: lastName, firstName: firstName } = user;


프로퍼티 키를 기준으로 디스트럭처링 할당이 가능하다.

const user = { firstName: 'Ungmo', lastName: 'Lee' };

// 프로퍼티 키를 기준으로 디스트럭처링 할당이 이루어진다.
// 프로퍼티 키가 lastName인 프로퍼티 값을 ln에 할당하고,
// 프로퍼티 키가 firstName인 프로퍼티 값을 fn에 할당한다.
const { lastName: ln, firstName: fn } = user;

console.log(fn, ln); // Ungmo Lee


const { firstName = 'Ungmo', lastName } = { lastName: 'Lee' };
console.log(firstName, lastName); // Ungmo Lee

const { firstName: fn = 'Ungmo', lastName: ln } = { lastName: 'Lee' };
console.log(fn, ln); // Ungmo Lee

겍체로부터 필요한 프로퍼티 키만 추출해 변수에 할당할 수 있는점은 유용하다.

const str = 'Hello';
// String 래퍼 객체로부터 length 프로퍼티만 추출한다.
const { length } = str;
console.log(length); // 5

const todo = { id: 1, content: 'HTML', completed: true };
// todo 객체로부터 id 프로퍼티만 추출한다.
const { id } = todo;
console.log(id); // 1


객체 디스트럭처링 할당은 함수의 매개변수에도 사용 가능하다.

function printTodo(todo) {
  console.log(`할일 ${todo.content}${todo.completed ? '완료' : '비완료'} 상태입니다.`);
}

printTodo({ id: 1, content: 'HTML', completed: true });
// 할일 HTML은 완료 상태입니다.

객체 디스트럭처링 할당을 매개변수에 잘 적용해 간단하면서 가독성이 더 좋아졌다.

function printTodo({ content, completed }) {
  console.log(`할일 ${content}${completed ? '완료' : '비완료'} 상태입니다.`);
}

printTodo({ id: 1, content: 'HTML', completed: true });
// 할일 HTML은 완료 상태입니다.


배열의 요소가 겍체이면 배열.객체 디스트럭처링 할당을 혼용 가능

const todos = [
  { id: 1, content: 'HTML', completed: true },
  { id: 2, content: 'CSS', completed: false },
  { id: 3, content: 'JS', completed: false }
];

// todos 배열의 두 번째 요소인 객체로부터 id 프로퍼티만 추출한다.
const [, { id }] = todos; 
console.log(id); // 2

const [, { id }] ',' 는 첫째 파라매터를 건너뛰고 두번째 파라미터가 활성화되어 todos의 두번째 요소의 id를 가르키게 만드는 역활을 해준다.



중첩 객체인 경우...

const user = {
  name: 'Lee',
  address: {
    zipCode: '03068',
    city: 'Seoul'
  }
};

// address 프로퍼티 키로 객체를 추출하고 이 객체의 city 프로퍼티 키로 값을 추출한다.
const { address: { city } } = user;
console.log(city); // 'Seoul'


Rest 프로퍼티 ...는 변수로 활용시에 반드시 마지막에 위치해야 한다.

// Rest 프로퍼티
const { x, ...rest } = { x: 1, y: 2, z: 3 };
console.log(x, rest); // 1 { y: 2, z: 3 }
profile
어떤 문제든 파악 할 수 있으며 해결책을 찾을 수 있는 개발능력을 꿈꾸고 있습니다.

0개의 댓글