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 }