비구조화 할당(destructuring assignment) 구문은 배열의 값이나 객체의 속성을 별개의 변수로 추출할 수 있게 하는 자바스크립트 식(expression)입니다.

구문

var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20


// Stage 3 proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); //{c: 30, d: 40}

설명

객체 및 배열 리터럴 식은 즉석에서 쉽게 데이터 패키지를 만들 수 있도록 합니다.

var x = [1, 2, 3, 4, 5];

비구조화 할당은 비슷한 구문이지만, 할당문의 좌변에 원래 변수에서 어떤 값들을 추출할지 정의합니다.

var x = [1, 2, 3, 4, 5];
var [y, z] = x;
console.log(y); // 1
console.log(z); // 2

이 기능은 Perl이나 Python 같은 언어에 존재하는 것과 비슷합니다.

배열 비구조화

기본 변수 할당

var foo = ["one", "two", "three"];

var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"

선언에서 분리한 할당

변수는 변수 선언에서 분리한 비구조화를 통해 그 값이 할당될 수 있습니다.

var a, b;

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

기본값

배열 인자의 값이 undefined인 경우에는 기본값을 할당할 수 있습니다.

var a, b;

[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7

변수 교환하기

두 변수 값은 비구조화 식을 이용하여, 하나로 교환될 수 있습니다.

만약, 비구조화 할당이 없으면, 두 변수 교환은 임시 변수 (또는 일부 저-레벨 언어에서는 XOR-swap 트릭) 가 필요합니다.

var a = 1;
var b = 3;

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

함수에서 반환된 배열 파싱

함수가 배열을 반환하는 경우가 있습니다. 비구조화는 반환된 배열 값을 통하여 작업을 더 간결하게 할 수 있습니다.

이 아래의 예제에서, f() 함수는 그 출력으로 값 [1, 2]를 반환하고,  배열 비구조화로 한 줄로 표현될 수 있습니다.

function f() {
  return [1, 2];
}

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

일부 반환값 무시하기

다음과 같이 관심 없는 반환값을 무시할 수 있습니다.

function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log(a); // 1
console.log(b); // 3

다음과 같이 모든 반환된 값을 무시할 수도 있습니다.

[,,] = f();

변수에 배열의 나머지를 할당하기

비구조화 할당시, rest 패턴을 이용해 배열의 남은 부분을 변수 하나에 할당할 수 있습니다.

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

rest element 다음에 trailing comma를 사용하면 SyntaxError가 발생될 것입니다.

var [a, ...b,] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma

정규식에서 일치하는 값 가져오기

정규식 exec() 메서드가 일치하는 부분를 발견하면, 먼저 문자열의 전체 일치하는 부분과 그 뒤에 정규식의 괄호로 묶인 각 그룹과 일치된 문자열 부분을 포함하는 배열을 반환합니다. 비구조화 할당은 필요하지 않은 경우 전체 일치하는 부분은 무시하고 필요한 부분만 쉽게 빼올 수 있습니다.

var url = "https://developer.mozilla.org/en-US/Web/JavaScript";

var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]

var [, protocol, fullhost, fullpath] = parsedURL;

console.log(protocol); // "https"

객체 비구조화

기본 할당

var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true

선언 없는 할당

변수의 선언과 분리하여 변수에 값을 할당할 수 있습니다.

var a, b;

({a, b} = {a: 1, b: 2});

할당 문을 둘러싼 ( .. )는 선언 없이 객체 리터럴 비구조화 할당을 사용할 때 필요한 구문입니다.

{a, b} = {a:1, b:2}는 유효한 독립 구문이 아닙니다. 좌변의 {a, b}이 블록으로 간주되고 객체 리터럴이 아니기 때문입니다.

그러나 ({a, b} = {a:1, b:2})는 유효한데, var {a, b} = {a:1, b:2}의 형태와 같습니다.

참고: ( .. ) 표현식 앞에 세미콜론이 없다면 이전 줄에 있는 함수 실행을 위해 이용될 수 있습니다.

새로운 변수 이름으로 할당하기

변수를 추출해서 원래 객체 속성명과는 다른 이름으로 할당시킬 수 있습니다.

var o = {p: 42, q: true};
var {p: foo, q: bar} = o;

console.log(foo); // 42
console.log(bar); // true

기본값

객체에서 가져온 값이 undefined인 경우, 변수에 기본값을 할당할 수 있습니다.

var {a = 10, b = 5} = {a: 3};

console.log(a); // 3
console.log(b); // 5

기본값을 제공하여 새로운 변수 이름으로 할당하기

새로운 변수명 할당과 기본값 할당을 한번에 할 수 있습니다.

var {a:aa = 10, b:bb = 5} = {a: 3};

console.log(aa); // 3
console.log(bb); // 5

함수 매개변수의 기본값 설정하기

ES5 버전

function drawES5Chart(options) {
  options = options === undefined ? {} : options;
  var size = options.size === undefined ? 'big' : options.size;
  var cords = options.cords === undefined ? { x: 0, y: 0 } : options.cords;
  var radius = options.radius === undefined ? 25 : options.radius;
  console.log(size, cords, radius);
  // 이제 드디어 차트 그리기 수행
}

drawES5Chart({
  cords: { x: 18, y: 30 },
  radius: 30
});

ES2015 버전

function drawES2015Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) {
  console.log(size, cords, radius);
  // 차트 그리기 수행
}

drawES2015Chart({
  cords: { x: 18, y: 30 },
  radius: 30
});

drawES2015Chart 를 보면, 비구조화된 좌변에 빈 오브젝트 리터럴을 할당하는 것을 볼 수 있습니다 {size = 'big', cords = {x: 0, y: 0}, radius = 25} = {}. 빈 오브젝트를 우변에 할당하지 않고도 함수를 작성할 수 있습니다. 그러나 지금의 형태에서는 drawES2015Chart() 처럼 어떤 매개변수 없이도 실행할 수 있지만, 빈 오브젝트 할당을 없앤다면 함수 실행시 적어도 하나의 인자가 제공되어야만 합니다. 만약 이 함수가 어떠한 매개변수 없이도 작동하길 원한다면 지금 형태가 유용하고, 무조건 객체를 넘기길 원하는 경우에는 빈 객체 할당을 하지 않는 것이 유용할 수 있습니다.

중첩 객체 및 배열 비구조화

var metadata = {
    title: "Scratchpad",
    translations: [
       {
        locale: "de",
        localization_tags: [ ],
        last_edit: "2014-04-14T08:43:37",
        url: "/de/docs/Tools/Scratchpad",
        title: "JavaScript-Umgebung"
       }
    ],
    url: "/en-US/docs/Tools/Scratchpad"
};

var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle);  // "JavaScript-Umgebung"

for of 반복문과 비구조화

var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith"
    },
    age: 35
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones"
    },
    age: 25
  }
];

for (var {name: n, family: { father: f } } of people) {
  console.log("Name: " + n + ", Father: " + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"

함수 매개변수로 전달된 객체에서 필드 가져오기

function userId({id}) {
  return id;
}

function whois({displayName: displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

var user = {
  id: 42,
  displayName: "jdoe",
  fullName: {
      firstName: "John",
      lastName: "Doe"
  }
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"

이 예제는 사용자 객체에서 id, displayNamefirstName 을 가져와 출력합니다.

계산된 속성 이름과 비구조화

계산된 속성 이름(computed property name)은, 객체 리터럴과 비슷하게 비구조화에도 사용될 수 있습니다.

let key = "z";
let { [key]: foo } = { z: "bar" };

console.log(foo); // "bar"

객체 비구조화시 나머지 (rest)

Rest/Spread Properties for ECMAScript 제안(stage 3)은 나머지 (rest) 구문을 비구조화에 추가합니다. 나머지 속성 구문은 비구조화를 이용해 추출하고 남은 객체의 enumerable한 속성들을 모두 모아줍니다.

let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10 
b; // 20 
rest; // { c: 30, d: 40 }

속성 이름이 유효한 자바스크립트 식별자명이 아닌 경우

비구조화는 자바스크립트 식별자명으로 적합하지 않은 속성명이 제공된 경우에도 이용할 수 있습니다. 이때는 대체할 유효한 식별자명을 제공해야 합니다.

const foo = { 'fizz-buzz': true };
const { 'fizz-buzz': fizzBuzz } = foo;

console.log(fizzBuzz); // "true"

스펙

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Destructuring assignment' in that specification.
Standard Initial definition.
ECMAScript Latest Draft (ECMA-262)
The definition of 'Destructuring assignment' in that specification.
Draft  
Rest/Spread Properties for ECMAScript Draft Stage 3 draft.

브라우저 호환성

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support4914411 No Yes8
Computed property names491434 No Yes No
Rest in arrays4914234 No Yes No
Rest in objects60 No55 No Yes No
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support494914411 Yes85.0
Computed property names49491434 Yes No5.0
Rest in arrays494914234 Yes No5.0
Rest in objects6060 No55 Yes No No

1. Firefox provided a non-standard destructuring implementation from Firefox 2 to 40.

2. From version 14: this feature is behind the Enable experimental Javascript features preference.

참조

문서 태그 및 공헌자

이 페이지의 공헌자: NessunKim, kdex, faker007, Netaras
최종 변경: NessunKim,