Destructuring

디스트럭처링 (Destructuring)

  • 구조화된 배열 또는 객체를 Destructuring(비구조화, 파괴)하여 개별적인 변수에 할당
  • 배열 또는 객체 리터럴에서 필요한 값만을 추출하여 변수에 할당하거나 반환할 때 유용함

배열 디스트럭처링 (Array destructuring)

// 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의 배열 디스트럭처링은 배열의 각 요소를 배열로부터 추출하여 변수 리스트에 할당. 이때 추출/할당 기준은 배열의 인덱스
// ES6 Destructuring
const arr = [1, 2, 3];

// 배열의 인덱스를 기준으로 배열로부터 요소를 추출하여 변수에 할당
// 변수 one, two, three가 선언되고 arr(initializer(초기화자))가 Destructuring(비구조화, 파괴)되어 할당된다.
const [one, two, three] = arr;
// 디스트럭처링을 사용할 때는 반드시 initializer(초기화자)를 할당해야 한다.
// const [one, two, three]; // SyntaxError: Missing initializer in destructuring declaration

console.log(one, two, three); // 1 2 3
  • 배열 디스트럭처링을 위해서는 할당 연산자 왼쪽에 배열 형태의 변수 리스트가 필요
let x, y, z;
[x, y, z] = [1, 2, 3];

// 위의 구문과 동치이다.
let [x, y, z] = [1, 2, 3];
  • 원하는만큼 패턴을 중첩시켜 사용
var [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
// 1
console.log(bar);
// 2
console.log(baz);
// 3
  • “레스트(rest)” 패턴을 사용해서 배열 맨뒤의 요소들 모두를 다른 배열에 할당
var [head, ...tail] = [1, 2, 3, 4];
console.log(tail);
// [2, 3, 4]
  • Date 객체에서 년도, 월, 일을 추출하는 예제
const today = new Date(); // Tue May 21 2019 22:19:42 GMT+0900 (한국 표준시)
const formattedDate = today.toISOString().substring(0, 10); // "2019-05-21"
const [year, month, day] = formattedDate.split('-');
console.log([year, month, day]); // [ '2019', '05', '21' ]

객체 디스트럭처링 (Object destructuring)

  • ES5에서 객체의 각 프로퍼티를 객체로부터 디스트럭처링하여 변수에 할당하기 위해서는 프로퍼티 이름(키)을 사용
// ES5
var obj = { firstName: 'Ungmo', lastName: 'Lee' };

var firstName = obj.firstName;
var lastName  = obj.lastName;

console.log(firstName, lastName); // Ungmo Lee
  • ES6의 객체 디스트럭처링은 객체의 각 프로퍼티를 객체로부터 추출하여 변수 리스트에 할당. 이때 할당 기준은 프로퍼티 이름(키)
// ES6 Destructuring
const obj = { firstName: 'Ungmo', lastName: 'Lee' };

// 프로퍼티 키를 기준으로 디스트럭처링 할당이 이루어진다. 순서는 의미가 없다.
// 변수 lastName, firstName가 선언되고 obj(initializer(초기화자))가 Destructuring(비구조화, 파괴)되어 할당된다.
const { lastName, firstName } = obj;

console.log(firstName, lastName); // Ungmo Lee
  • 객체 디스트럭처링을 위해서는 할당 연산자 왼쪽에 객체 형태의 변수 리스트가 필요
// 프로퍼티 키가 prop1인 프로퍼티의 값을 변수 p1에 할당
// 프로퍼티 키가 prop2인 프로퍼티의 값을 변수 p2에 할당
const { prop1: p1, prop2: p2 } = { prop1: 'a', prop2: 'b' };
console.log(p1, p2); // 'a' 'b'
console.log({ prop1: p1, prop2: p2 }); // { prop1: 'a', prop2: 'b' }

// 아래는 위의 축약형이다
const { prop1, prop2 } = { prop1: 'a', prop2: 'b' };
console.log({ prop1, prop2 }); // { prop1: 'a', prop2: 'b' }

// default value
const { prop1, prop2, prop3 = 'c' } = { prop1: 'a', prop2: 'b' };
console.log({ prop1, prop2, prop3 }); // { prop1: 'a', prop2: 'b', prop3: 'c' }
  • 객체 디스트럭처링은 객체에서 프로퍼티 이름(키)으로 필요한 프로퍼티 값만을 추출할 수 있음
const todos = [
  { id: 1, content: 'HTML', completed: true },
  { id: 2, content: 'CSS', completed: false },
  { id: 3, content: 'JS', completed: false }
];

// todos 배열의 요소인 객체로부터 completed 프로퍼티만을 추출한다.
const completedTodos = todos.filter(({ completed }) => completed);
console.log(completedTodos); // [ { id: 1, content: 'HTML', completed: true } ]
  • Array.prototype.filter 메소드의 콜백 함수는 대상 배열(todos)을 순회하며 첫 번째 인자로 대상 배열의 요소를 받음. 이때 필요한 프로퍼티(completed 프로퍼티)만을 추출

객체도, 배열도, 이터러블(iterable)도 아닌 값을 디스트럭처링 하기

  • null이나 undefined를 디스트럭처링하려고 하면 타입 에러(type error)가 발생
var {blowUp} = null;
// TypeError: null has no properties
  • boolean, number, string 같은 프리미티브 타입(primitive type)들은 에러 없이 디스트럭처링할 수 있지만 결과값으로 undefined
var {wtf} = NaN;
console.log(wtf);
// undefined
  • 객체 할당 패턴을 사용할 때, 디스트럭처링의 대상이되는 값은 Object로 변환 가능한 값이어야 함. 거의 모든 타입이 객체로 변환 가능함
  • 하지만 null과 undefined는 변환되지 않음. 배열 할당 패턴을 적용할 때, 그 값은 반드시 이터레이터(iterator)를 갖고 있어야 함

디스트럭처링의 응용

함수의 인자 정의

  • API를 만들 때, API 사용자가 API의 파라메터 순서를 기억하도록 강요하는 것보다 여러개의 속성을 가진 객체를 파라메터로 전달 받는 것이 좀 더 나은 접근
  • 디스트럭처링을 이용하면 API 함수 안에서 파라메터 속성을 참조할 때마다 파라메터 객체를 반복해서 사용하는 것을 피할 수 있음
function removeBreakpoint({ url, line, column }) {
  // ...
}

ES6 이터레이션 프로토콜과 함께 사용

  • ECMAScript 6는 이터레이션 프로토콜을 제공
var map = new Map();
map.set(window, "the global");
map.set(document, "the document");

for (var [key, value] of map) {
  console.log(key + " is " + value);
}
// "[object Window] is the global"
// "[object HTMLDocument] is the document"
  • 순회하면서 key 값에만 접근
for (var [key] of map) {
  // ...
}
  • 순회하면서 value 값에만 접근
for (var [,value] of map) {
  // ...
}

여러개의 값을 리턴하기

  • 배열을 리턴하고 그 결과를 디스트럭처링할 수 있기 때문에 여러개의 값을 리턴하는 기능을 대신함
function returnMultipleValues() {
  return [1, 2];
}
var [foo, bar] = returnMultipleValues();
function returnMultipleValues() {
  return {
    foo: 1,
    bar: 2
  };
}
var { foo, bar } = returnMultipleValues();

Comments