ES6 const

24 Feb 2016

1. 글에 대해

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

2. const 키워드

  • const 키워드는 let 키워드와 유사한 언어 매커니즘을 가지고있다.

3. ES5 & const

  • Object.defineProperty or create 메서드를 통해, 읽기전용 속성을 생성할 수 있다(단 일반적인 방법으로 (속성)재 할당const 키워드와 같은 예외가 발생하지는 않는다)

    ```javascript
    // global ec
      
    // globalEC.VO 객체에 읽기 전용 속성을 생성한다.(이떄 생성된 a 속성은 변수가 아니다)
    Object.defineProperty(this, 'a', {
        writable: false,
        value: 1
    });
      
    // VO 객체의 a 속성 값을 변경한다.
    a = 2;
      
    // 읽기 전용 속성으로 값이 변경되지않는다.
    console.log(a); // 1
      
    // writable 속성의 기본값은 false 이며, 반드시 속성을 정의할 필요는 없다.
    Object.defineProperty(this, 'b', {
    //    writable: false,
        value: 1
    });
      
    // VO 객체의 b 속성 값을 변경한다.
    b = 2;
      
    // 읽기 전용 속성으로 값이 변경되지않는다.
    console.log(b); // 1
      
      
    // global ec
      
    (function A(){
      
        // A function ec
      
        // AO 객체는 직접 접근할 수 없다. 즉 AO 객체의 읽기 전용 속성을 생성할 수 없다는 단점이 존재한다.
      
        // 하지만 ES6 의 const 키워드를 통해서는 생성 가능하다.
        const a = 1;
      
        console.log(a); // 1
      
    })();
      
      
    // obj 객체에 읽기 전용 속성 생성하기
    var obj = {};
      
    // Object.defineProperty 메서드를 통해 생성하는 방법은 아래와 같다.
    Object.defineProperty(obj, 'x', {
        writable: false,
        value: 1
    });
      
    // 속성값을 변경한다
    obj.x = 2;
      
    // 읽기 전용 속성으로 값이 변경되지않는다.
    console.log(obj.x); // 1
      
      
    // Object.create 메서드를 통해 생성하는 방법은 아래와 같다.
    var obj2 = Object.create(Object.prototype, {
        x: {
            writable: false,
            value: 1
        }
    });
      
    // 속성값을 변경한다
    obj2.x = 2;
      
    // 읽기 전용 속성으로 값이 변경되지않는다.
    console.log(obj2.x); // 1
      
      
    // 인스턴스의 속성을 읽기 전용으로 초기화하는 방법은 아래와 같다.
    function A(){
      
        if (!(this instanceof A)) return;
      
        // 읽기 전용
        Object.defineProperty(this, 'x', {
            writable: false,
            value: 1
        });
      
        // 읽기/쓰기
        Object.defineProperty(this, 'y', {
            writable: true,
            value: 1
        });
    }
      
    // 새로운 인스턴스를 생성한다.
    var newAObject = new A;
      
    // 생성된 인스턴스의 속성값을 변경한다
    newAObject.x = 2;
      
    // 생성된 인스턴스의 속성값을 변경한다
    newAObject.y = 2;
      
    // 읽기 전용 속성으로 값이 변경되지않는다.
    console.log(newAObject.x); // 1
      
    // 읽기/쓰기 속성이며, 변경된 값인 2를 반환한다.
    console.log(newAObject.y); // 2
    ```
    
  • Object.defineProperty 메서드를 통해, 읽기 전용 속성을 재 정의 시, 재 정의대한 예외가 발생하게된다.

    ```javascript
    Object.defineProperty(this, 'a', {
        writable: false,
        value: 1
    });
      
    // 단 Object.defineProperty 메서드를 통해 읽기 전용 속성을 재 정의 시, 재 정의에 대한 예외가 발생하게된다.
    try{
      
        Object.defineProperty(this, 'a', {
            writable: false,
            value: 2
        });
    }
    catch(e){
        // Cannot redefine property: a
        console.log(e.message);
    }
    ```      
    

4. ES6 & const

  • const 키워드를 통해 선언된 상수는, 블럭 범위의 Isolated Scope(격리된 유효범위) 를 갖게된다.

          
      {
          // block scope
          
          // const 키워드를 통한 변수 선언
          const a = 1;
      }
          
      if (true){
          const b = 2;
      }
          
      switch (1){
          case 1:
              const c = 3;
              break;
      }
          
      for (var d = 0; d < 3; d++){
          const _d = d;
          console.log(_d); // 0, 1, 2
      }
          
          
      const e = 4;
          
          
      try {
          // 실행 코드 처리 시, 블록 범위에 선언된 a 상수는 선언되지 않았다는 예외가 발생하게 된다.
          console.log(a);
      }
      catch(e){
          // a is not defined
          console.log(e.message);
      }
          
      try {
          // 실행 코드 처리 시, 블록 범위에 선언된 b 상수는 선언되지 않았다는 예외가 발생하게 된다.
          console.log(b);
      }
      catch(e){
          // b is not defined
          console.log(e.message);
      }
          
      try {
          // 실행 코드 처리 시, 블록 범위에 선언된 c 상수는 선언되지 않았다는 예외가 발생하게 된다.
          console.log(c);
      }
      catch(e){
          // c is not defined
          console.log(e.message);
      }
          
      try {
          // 실행 코드 처리 시, 블록 범위에 선언된 d 상수는 선언되지 않았다는 예외가 발생하게 된다.
          console.log(_d);
      }
      catch(e){
          // _d is not defined
          console.log(e.message);
      }
          
      console.log(e); // 4
    
  • const 키워드를 통해 선언된 상수유효 범위는 자신을 포함한 블럭 및 그 내부 블럭까지 유효하다.

      {
          const a = 1;
          
          {
              const b = 2;
          
              {
                  const c = 3;
          
                  {
                      const d = 4;
          
                      // 선언된 상수의 유효 범위는 자신을 포함한 블럭 및 그 내부 블럭까지 유효하다
                      console.log(a, b, c, d); // 1, 2, 3, 4
                  }
              }
          }
          
          console.log(a); // 1;
          
          // 해당 블럭 Scope 에서는 b 상수에 접근할 수 없다.
          try{
              console.log(b);
          }
          catch(e){
              // b is not defined
              console.log(e.message);
          }
          
      }
    
  • 동일 블럭 범위에서, 동일한 식별자 이름으로 상수를 재 선언예외가 발생하게된다.

      // 동일 블럭 범위에서, 동일한 식별자 이름으로 변수를 재 선언시, 아래와 같은 예외가 발생하게된다.
          
      const a = 1;
      // Uncaught SyntaxError: Identifier 'a' has already been declared
      const a = 2;
          
      const obj = {};
      const obj = {}; // Uncaught SyntaxError: Identifier 'obj' has already been declared
          
          
      {
          const b = 1;
          // Uncaught SyntaxError: Identifier 'b' has already been declared
          const b = 2;
      }
          
      if (true){
          const i = 1;
          const i = 2; // Uncaught SyntaxError: Identifier 'i' has already been declared
      }
          
      (function A(){
          const c = 1;
          const c = 2; // Uncaught SyntaxError: Identifier 'c' has already been declared
      })();
          
          
      // 다른 식별자 이름으로 선언 시 예외가 발생하지 않는다.
      {
          const c = 1;
          const d = 2;
          
          console.log(d); // 2
      }
    
  • const 키워드를 통해 선언된 상수 재 할당 시 예외가 발생하게 된다.

      const a = 1;
          
      // Uncaught TypeError: Assignment to constant variable.
      a = 2;
          
      // 당연한 말이겠지만, 선언된 obj 객체의 속성까지 상수 범위가 적용되지는않는다.
      const obj = {x: 1};
          
      // x 속성은 읽기/쓰기 속성으로 선언되어있다.
          
      // Object {value: 1, writable: true, enumerable: true, configurable: true}
      console.log(Object.getOwnPropertyDescriptor(obj, 'x')); 
          
          
      obj.x = 2;
          
      console.log(obj.x); // 2
          
    
  • const 키워드를 통해 선언된 상수EC 진입 및 실행 코드 처리 후에도 VO 의 새로운 속성으로 추가되지않는다..

      // global ec 진입 시 VO 의 새로운 속성으로 추가되지않는다.
      try {
          console.log(a); // a is not defined
      }
      catch(e){
          console.log(e.message);
      }
          
      const a = 1;
          
      // 할당된 값을 반환한다.
      console.log(a); // 1
          
      // 실행 코드 처리후에도 VO 의 새로운 속성으로 추가되지않는다.
      console.log(window.a); // undefined
    
  • 동일 VO(AO) 범위에서, 동일한 식별자 이름으로 변수(or 함수) 선언예외가 발생하게 된다.(단 const 키워드를 통해 선언된 변수는 VO 의 속성으로 추가되지않는다)

          
      // 테스트 1
      // global ec
      const a = 1;
      // globalEC.VO.a
      var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
          
          
      // 테스트 2
      // global ec
      const a = 1;
      {
          // globalEC.VO.a
          var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
      }
          
      // 테스트 3
      // global ec
      const a = 1;
          
      if (true){
          // globalEC.VO.a
          var a; // Uncaught SyntaxError: Identifier 'a' has already been declared
      }
          
      // 테스트 4
      // global ec
      const a = 1;
          
      // globalEC.VO.a
      // Uncaught SyntaxError: Identifier 'a' has already been declared
      function a(){
          
          // a function ec
      }
          
      // 테스트 5
      // global ec
      const a = 1;
          
      (function A(){
          
          // A function ec
          
          // 이 경우 a 변수는 globalEC.VO 의 속성으로 추가되며, 마찬가지로 예외가 발생하게된다.
          
          a; // Uncaught SyntaxError: Identifier 'a' has already been declared
      })();
          
          
      // 테스트 6
      // global ec
      (function A(){
          
          // function ec
          
          const a = 1;
          
          // 이 경우 a 변수는 AFunctionEC.AO 의 속성으로 추가되며, 마찬가지로 예외가 발생하게된다.
          var a;
      })();
          
          
      // 테스트 7
      // global ec
      const a;
          
      (function A(){
          
          // A function ec
          
          // 이 경우 a 변수는 AFunctionEC.AO 의 속성으로 추가되며, 예외가 발생하지않는다.
          var a;
          
          console.log(a); // undefined
      })();
    
    
  • 루프(for, while 등)문 내부에서 (const 키워드를 통해)선언된 변수는, 비동기 함수안에서 각기 다른 상수참조하게된다.(즉 각 루프는 서로 다른 상수(값)를 가지게 된다)

          
      // global scope
      for (var i = 0; i < 10; i++) {
          
          // block scope
          
          // 루프문 내부에 const 키워드를 통해 선언된 상수
          const _i = i;
          
          window.setTimeout(function() {
          
              // 이 경우 _i 상수는 각기 다른 상수 값을 참조하게된다.
              console.log(_i); // 0 ~ 9
          
              // var 키워드를 통해 선언된 i 변수는, 함수 Scope Chain 매커니즘에 의해 최종 증감값인 10을 참조하게된다.
              console.log(i); // 10
          });
      }
          
      console.log(i); // 10;
          
          
      var i = 4;
      while (i) {
          
          // block scope
          
          const _i = i;
          // const 키워드를 통해 상수를 선언한다.
          window.setTimeout(function() {
              // 이 경우 _i 상수는 각기 다른 변수 값을 참조하게된다.
              console.log(_i); // 4 ~ 1
          });
          
          i--;
      }
          
      // ES5 를 통한 구현은 아래와 같다.
      for (var i = 0; i < 10; i++){
          
          // 루프 순회 시 (읽기 전용 속성)재 정의에 대한 예외가 발생하게 된다.
          
          // Uncaught TypeError: Cannot redefine property: _i
          Object.defineProperty(this, '_i', {
              writable: false,
              value: i
          });
          
          window.setTimeout(function(){
              console.log(_i); // 0 ... error
          });
      }
         
    
  • eval 함수를 통해, 선언된 상수는 local sandbox 안에서 평가된다.

          
      eval('const i = 1');
          
      try{
          i;
      }
      catch(e){
          console.log(e.message); // i is not defined
      }
         
    

관련 URL

comments powered by Disqus