ES6 const

February 24, 2016

1. 글에 대해

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

2. const 키워드

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

3. ES5 & const

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

    // 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 메서드를 통해, 읽기 전용 속성을 재 정의 시, 재 정의대한 예외가 발생하게된다.

    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


Profile picture

Written by mohwa