ES6 Destructuring assignment

March 24, 2016

1. 글에 대해

  • 모든 결과는 Chrome 브라우저(ver 49)를 통해 테스트된 결과입니다.

2. Destructuring assignment(해체 할당)이란?

  • 해체 할당은, 배열 또는 객체 리터럴과 유사한 문법으로, 변수에 값을 할당하는 JS 표현식중 하나이다.

3. Array destructing assignment(배열 해체 할당)

  • 배열 해체 할당을 통해, iterator 객체의 요소값을, 변수에 할당시킬 수 있다.

    • Array in ES5

      {
        // ES5 에서, 배열 객체 요소를 변수에 할당시키는 기본적인 방법이다.
        var arr = [1, 2];
      
        var x = arr[0];
        var y = arr[1];
      
        console.log(x, y); // 1 2
      }
      
    • Iterator in ES6

      • 기본적인 할당 방법

        {
          let arr = [1, 2];
        
          // (블록 스코프)변수 선언과, 해체 할당을 한줄로 표현할 수 있다.
          let [x, y] = arr;
        
          console.log(x, y); // 1 2
        
          // 변수 선언이 생략된 x, y 속성은, 실행 코드 처리 시, globalEC.VO 의 속성으로 추가된다.
          [_x, _y] = arr;
        
          // globalEC.VO.x, globalEC.VO.y
          console.log(this._x, this._y, window._x, window._y); // 1 2 1 2
        }
      • 변수 할당을 건너뛰는 방법

        {
          let arr = [1, 2, 3, 4];
        
          // 아래와 같은 표현식을 통해, 변수 할당을 건너뛸 수 있다.
          let [x, , , z] = arr;
        
          console.log(x, z); // 1 4
        }
      • 나머지 연산자를 통한 해체 할당

        {
            let arr = [1, 2, 3];
        
            // y 변수에는, (할당될)배열 객체의 나머지 요소(2, 3)가 포함된 새로운 배열 객체([2, 3])가 할당된다.
            let [x, ...y] = arr;
        
            console.log(x, y); // 1 [2, 3]
        
            let [_x, ..._y] = [1];
        
            // _y 변수에는, (할당될)배열 객체의 나머지 요소가 존재하지 않으므로, 빈 배열 객체가 할당된다.
            console.log(_x, _y); // 1, []
        }
        • (할당될)변수의 기본값을 지정할 수 있다.

          {
              let arr = [1];
          
              // y 변수에 기본값 2 를 지정한다.
              let [x, y = 2] = arr;
          
              // y 변수에 기본값 2 가 할당된다.
              console.log(x, y); // 1 2
          
              // _x 변수에 기본값 1 을 지정한다.
              let [_x = 1] = [undefined];
          
              // _x 변수에 기본값 1 이 할당된다.
              console.log(_x); // 1
          
              // 함수 표현식을 기본값으로 사용할 수 있다.
              let [__x = (() => {
                  return 1;
              })()] = [];
          
              // __x 변수에 함수 표현식을 통해 반환받은 기본값 1이 할당된다.
              console.log(__x); // 1
          
              // ___x, ___y 변수에 각각 기본값 3, ___x 변수를 지정한다.
              let [___x = 3, ___y = ___x] = [];
          
              // ___x, ___y 변수에 각각 기본값 3, ___x 변수값이 할당된다.
              console.log(___x, ___y); // 3 3
          
              // ____x, ____y 변수에 각각 기본값 3, ____x 변수를 지정한다.
              let [____x = 3, ____y = ____x] = [7];
          
              // ____x, ____y 변수에 각각 배열 요소값 7, ____x 변수값이 할당된다.
              console.log(____x, ____y); // 7 7
          }
        • 중첩 배열에 대한, 해체 할당

          {
            // 중첩 배열을 통한 해체 할당
            let arr = [1, [3, 4, 5]];
          
            let [x, [y, ...z]] = arr;
          
            // z 변수에는 (할당될)변수 객체의 나머지 요소(4, 5)가 포함된 새로운 배열[4, 5]이 할당된다.
            console.log(x, y, z); // 1 3 [4, 5]
          
            let [_x, ...[_y, _z]] = [1, 2, 3];
          
            // (나머지 연산자의)피 연산자는 꼭 변수가 아니여도 된다.
            // 즉 나머지 연산자를 통해, 할당된 피연산자를 한번 더, 해체 할당하면 아래와 같은 결과가 반환된다.
            console.log(_x, _y, _z); // 1 2 3
          }
        • 함수 인자값을 통한, 해체 할당

          {
          
              let A = ([x, y = 2]) => {
          
                  // y 변수에는 지정된 기본값인 2가 할당된다.
                  console.log(x, y); // 1 2
              };
          
              A([1]);
          
              let B = ([x, y] = [1, 2]) => {
          
                  // x, y 변수에는 지정된 기본값인 1, 2 가 할당된다.
                  console.log(x, y); // 1 2
              };
          
              B();
          
              let C = ([x = 1, y = 2] = []) => {
                  console.log(x, y);
              };
          
              // 전달된 인자값이 없는경우, 그에 대한 기본값인 "빈 배열" 객체가 할당되며,
              // 또 그 배열에 대한 기본값인 x = 1, y = 2 가 다시 할당되게된다.
              C(); // 1 2
          
              // 지정된 기본값인 1, 2 가 할당된다.
              C([]); // 1 2
          
              // 전달된 인자값이 할당된다.
              C([3, 4]); // 3 4
          
          
              // block scope
              let x = 'outer';
          
              let D = function(_x = x) {
          
                  // x 변수 선언 후, 2를 할당한다
                  let x = 'inner';
                  console.log(_x); // outer
              }
          
              // 전달된 인자값이 없는 경우, 지정된 기본값인 x 변수가 할당된다.
              D();
          
              // args 변수에는, 전달된 인자값이 모두 포함된 새로운 배열이 할당된다.
              let E = function(...args) {
          
                  // x, y 변수에 할당한다.
                  let [x, y] = args;
          
                  console.log(x, y); // 1 2
              }
          
              E(1, 2);
          }
          
      • 그 밖의 표현식

        • 문자열 할당

          {
          
              // 문자열이 할당될 경우에는, 해당 문자열을 암묵적으로 iterator 객체로 변환한다.
              let [x, y, z] = 'xyz';
          
              console.log(x, y, z); // x y z
          
              // 아래 코드는 동일한 결과를 반환한다.
              // let [_x, _y, _z] = new String('xyz')[Symbol.iterator]();
          }
          
        • new Set([])

          {
              // 생성된 set 객체를 통해, iterator 객체를 할당한다.
              let [__x, __y] = new Set([1, 2]);
          
              console.log(__x, __y); // 1 2
          
              // let [__x, __y] = new Set([1, 2]).values();
          }
        • generator 할당

          {
              // generator 를 선언한다.
              function* $$() {
                  for (let i = 1; ; i++) {
                      yield i;
                  }
              }
          
              // 생성된 generator 를 할당한다.
              let [x, y, z] = $$();
          
              console.log(x, y, z); // 1 2 3
          
              // 객체 내부에 생성된 generator 를 할당한다.
              let [_x, _y] = {
                  // generator 생성한다
                  * [Symbol.iterator]() {
                      for (let i = 1; i < 10; i++){
                          yield i;
                      }
                  }
              };
          
              console.log(_x, _y); // 1 2
          
              // iterator 인터페이스를 구현한, iterator 객체를 할당한다.
              let [__x, __y] = {
                  i: 0,
                  [Symbol.iterator]() {
                      // iterator 객체를 반환
                      return this;
                  },
                  next(){
                      return {value: ++this.i, done: this.i > 10};
                  }
              };
          
              console.log(__x, __y); // 1 2
          }
        • ETC

          {
          
              // 정규식을 통해, 반환된 iterator 객체를 할당한다.
              let [, x, y, z] = /(\d+)\/*(\d+)\/*(\d+)/.exec('2016/03/01');
              console.log(x, y, z); // 2016 03 01
          
          
              // map 객체를 생성한다.
              let m = new Map([
                  [1, 'a'],
                  [2, 'b'],
                  [3, 'c']
              ]);
          
              // map 객체를 통해, 새로운 배열 객체를 생성한다.
              let _m = new Map([...m].map(([k, v]) => {
                  return [k * 2, '_' + v];
              }));
          
          
              let urls = [
                  'http://example.com/foo.html',
                  'http://example.com/bar.html',
                  'http://example.com/baz.html'
              ];
          
              // Promise.all 메서드를 통해, 전달된 url 집합을 할당한다.
              Promise.all(urls.map((url) => {
                  return url;
              })).then(([url1 = top.window.location.href, url2 = top.window.location.href, url3 = top.window.location.href]) => {
          
                  // 전달받은 배열 객체(['http://example.com/foo.html', 'http://example.com/bar.html', 'http://example.com/baz.html'])가 해체 할당된다.
                  console.log(url1, url2, url3);
              });
          }

4. Object destructing assignment(객체 해체 할당)

  • 객체 해체 할당을 통해, 객체 속성값을, 변수에 할당시킬 수 있다.

    • Object in ES5

      
      {
          // ES5 에서, 객체 속성을 변수에 할당시키는 기본적인 방법이다.
          let o = {x: 1, y: 2};
          
          let x = o.x;
          let y = o.y;
      
          console.log(x, y); // 1 2
      }                    
    • Object in ES6

      • 기본적인 할당 방법

        {
            let o = {x: 1, y: 2};
        
            // (블록 스코프)변수 선언과, 해체 할당을 한줄로 표현할 수 있다.
            let {x, y} = o;
        
            // (할당될)변수 이름을 객체 속성 이름과 다르게 생성하고 싶을때에는, 아래와 같은 표현식을 사용할 수 있다.
            let {x: _x, y: _y} = o;
        
            console.log(x, y, _x, _y); // 1 2 1 2
        }
      • (할당될)변수의 기본값을 지정할 수 있다.

        {
            let o = {x: 1};
        
            // y 변수에 기본값 2 를 지정한다.
            let {x, y = 2} = o;
        
            console.log(x, y); // 1 2
        
            // _y 변수에 기본값 2 를 지정한다.
            let {x: _x, y: _y = 2} = o;
        
            console.log(_x, _y); // 1 2
        
        
            // 배열 요소가 존재하지 않을 경우, 그에 대한 기본값인 "빈 객체"가 할당되며,
            // 또 그 객체에 대한 기본값인 __y = 2 가 다시 할당된다.
            let [{x: __x, y: __y = 2} = {}] = [];
        
            console.log(__x, __y); // undefined 2
        
        
            // 배열 요소가 존재하지 않을 경우, 그에 대한 기본값인 "빈 객체"가 할당되며,
            // 또 그 객체에 대한 기본값인 ___x = {x: 1}, ___y = 2 가 다시 할당된다.
            let [{x: ___x, y: ___y = 2} = {x: 1}] = [];
        
            console.log(___x, ___y); // 1 2
        }
      • 중첩 객체에 대한, 해체 할당

        {
            // 중첩된 객체를 생성한다.
            let o = {x: 1, y: {_x: 2, _y: {__x: 3}}};
            
            // 중첩된 객체가 해체 할당된다.
            let {x, y: {_x, _y: {__x}}} = o;
        
            console.log(x, _x, __x); // 1 2 3
        }
      • 함수 인자값을 통한, 해체 할당

        {
            let A = ({x = 1, y = 2}) => {
                console.log(x, y); // 1 2
            };
        
            // y 변수에는 기본값인 2가 할당된다.
            A({x: 1});
        
            let B = ({x, y} = {x: 1, y: 2}) => {
                console.log(x, y); // 1 2
            };
        
            // 인자값이 전달되지않은 경우에도, 기본값인 {x: 1, y: 2} 가 할당된다.
            B();
        
            let C = ({x = 1, y = 2} = {}) => {
                console.log(x, y); // 1 2
            };
        
            // 인자값이 전달되지않은 경우에는, 그에 대한 기본값인 빈 객체가 할당되며,
            // 또 그 객체에 대한 기본값인 x = 1, y = 2 가 다시 할당된다.
            C();
            
          // 해체 할당을 통해 이와 같은 패턴이 적용될듯 하다.
          function ajax({url = top.location.href, method = 'GET', headers = {}} = {}){
        
              return {
                  url: url,
                  method: method,
                  headers: headers
              };
          };
        
          console.log(ajax()); // {url: "http://localhost:8080/sourceTest/es6/destructuring_assignment.html", method: "GET", headers: Object}
          
          console.log(ajax({url: 'myUrl', method: 'POST', headers: {contentType: ''}})); // {url: "myUrl", method: "POST", headers: Object}                  
        }
    • 그 밖의 표현식

      • (할당)패턴 없이, 값을 할당할 경우에는 그 값을 객체로 변환 후, 해당 속성값을 할당시킨다

        {
        
            let {length: x} = [1] // [].length
            console.log(x); // 1
        
            let {toString: xx} = {} // {}.toString
            console.log(xx); // toString function object
            
            // 할당될 값에 (할당)패턴이 적용된 경우...
            let {toString: _xx} = {toString: 1} // {}.toString
            console.log(_xx); // 1                  
        
            let {length: xxx} = 'mohwa'; // === new String('mohwa').length
            console.log(xxx); // 5
        
            let {toString: xxxx} = 'mohwa'; // === new String('mohwa').toString
            console.log(xxxx); // toString function object
        
            let {toFixed: xxxxx} = 1; // new Number(1).toFixed
            console.log(xxxxx); // toFixed function object
        
            let {valueOf: xxxxxx} = true; // new Boolean(true).valueOf
            console.log(xxxxxx); // valueOf function object
        
            let {length: xxxxxxx} = function(x){}; // function(x){}.length
            console.log(xxxxxxx); // 1
        
            let {x: xxxxxxxx} = 'mohwa'; // new String('mohwa').xx
            console.log(xxxxxxxx); // undefined
        
        
            // undefined 와 null 값은 예외가 발생한다.
        
            try{
                let {toString: x} = undefined; // === undefined.toString
            }
            catch(e){
                console.log(e.message); // Cannot match against 'undefined' or 'null'.
            }
        
            try{
                let {toString: x} = null; // === null.toString
            }
            catch(e){
                console.log(e.message); // Cannot match against 'undefined' or 'null'.
            }
        
        }
      • Symbol 을 통한 해체 할당

        {
            const k = Symbol();
            let o = { [k]: 1 };
        
            let {[k]: x} = o;
        
            console.log(x); // 1
        }        

관련 URL


Profile picture

Written by mohwa