본문 바로가기
javascript

[자바스크립트] ECMA6 - let, const 블록 레벨 스코프

by jinbro 2017. 6. 16.
[자바스크립트 스코프]
- 자바스크립트의 변수 범위는 블록( { …. } )이 아닌 function level scope
- 함수 바깥에 정의된 변수와 함수는 전역 객체(window)의 멤버
- 함수 내부에서 var 키워드로 변수를 선언하지않으면 전역객체의 멤버로 정의됨
- 전역변수의 남발


[블록 레벨 스코프]
- ES6부터 추가된 문법을 통해 블록 레벨 스코프 변수를 선언할 수 있음
- 기존 함수 레벨 스코프를 가지는 var로 변수를 선언하면 전역변수 or 함수의 변수


[let]
1) 블록 레벨 스코프 변수 선언 키워드
var test = function(a, b, start){     
     if(start){
          let result = a + b;    
     }

     return result;
}

test(1, 2, true); // undefined 
- result는 let으로 선언되었기때문에 스코프는 if문 안에서만 유효함
- if문 바깥의 result는 test 함수 내부 변수나 전역객체에서 찾으려고 했으나 못찾으면서 undefined를 리턴


2) var는 여러번 같은 변수명으로 선언하는 것이 가능하나 let으로 선언하는 변수는 블록 안에서 1개만 존재
var name = 'jinbro';

{
     var name = 'jinhyung park';
}

var test = function(){
     var name = 'jinhyung';
     console.log(name);  // jinhyung

     let age = 26;
     let age = 26;
}

console.log(name); // jinhyung park


test(); 
- syntax error 발생함 : 두개의 같은 변수명을 가진 let 변수가 선언되었기 때문에
- var로 선언한 경우 전역객체의 멤버와 함수 객체의 멤버로 갈릴 뿐 아니라 새로운 값을 재할당함


3) 호이스팅에서의 차이
- 호이스팅이란? 자바스크립트의 변수 선언부와 할당문을 구분하고 선언부를 모두 끌어올려 초기화 시키는 것
- 초기화 값은 undefined
- 총 3단계
(1) 선언 : Variable Object 스코프에 등록함
(2) 초기화 : undefined로 초기화
(3) 할당 : 실제 값을 할당 - 실행될 때(할당문에 도달했을 때)


- var 변수는 선언과 초기화 단계를 한번에 함 : 코드 상에서 할당문 전에 접근하여도 undefined를 리턴하지 에러나지않음
console.log(a); // undefined

var a = 10;


- let 변수는 선언과 초기화 단계를 쪼갬 : Variable Object 스코프에 등록하지만, 초기화는 하지않고 할당문을 만났을 때 초기화함
- 할당 단계가 곧 초기화 단계가 된 것
console.log(b); // uncaught reference error 발생, b is not defined

let b = 20;


4) 클로저 : let을 사용한다면 코드가 간결해짐
- 외부함수가 return으로 종료가 되어 스코프 참조를 못할 것 같지만 내부 함수가 외부 함수의 scope를 참조할 수 있음
var outer = function(){
     var time = 0;

     return function(){
          return time++;
     }
}

var inner = outer();
inner(); // 0, innerVO - outer VO scope chain - time
inner(); // 1
inner(); // 2
inner(); // 3

var inner2 = outer();

inner2(); // 0



- var로 for문에 i를 선언할 경우 i는 전역 변수가 되고, arr에 푸쉬된 함수들은 실행할 때 i를 참조하는데, 전역변수 i를 참조하기때문에 3이 세번 출력됨
var arr = [];

for(var i=0; i<3; i++){
    arr.push(function () { console.log(i) });
}

for(var j=0; j



- for문의 i를 let으로 선언할 경우 함수가 참조하는 값의 i는 블록 레벨 스코프의 i, 함수가 존재하는 한 i는 지속적으로 생존
var arr = [];

for(let i=0; i<3; i++){
     arr.push( function () { console.log(i) } );
}

for(var j=0; j



- 아래는 arr[j](익명함수) 내부임, 스코프 정보를 보면 block 프로퍼티가 있음




5) 전역객체의 프로퍼티
- var로 전역변수 선언한다면 window 객체의 프로퍼티가 됨 : 변수가 함수에서 var로 선언되지않고
var isGlobal = true;
console.log(window.isGlobal); // true



- let으로 전역변수를 선언하면 window 객체 프로퍼티가 되지않음 
let isGlobal = false;
console.log(window.isGlobal); // undefined


[const]
- 변수 선언 키워드
- 읽기 전용을 만듬 
- let과 마찬가지로 블록 레벨 스코프를 가짐
- let과의 차이점이 있음

1) let은 값 재할당은 가능하지만, const는 재할당하지못함
let a = 10;
a = 20;

const b = 10;
b = 20; // Uncaught TypeError: Assignment to constant variable




2) const로 선언된 객체 : 객체 주소값이 변수에 바인딩되면 변수에 바인딩된 주소값을 바꿀 수 없음
const jinbro = {};
jinbro.name = 'jinbro';

jinbro = {}; // 새로운 객체 할당, 불가 Uncaught TypeError: Assignment to constant variable
- 값(값, 객체주소)을 재할당(변경)하는 것은 불가하나, 객체주소가 가리키는 객체의 프로퍼티 변경은 가능함


3) 바인딩되는 값을 변경하지않는 경우에는 우선적으로 const를 사용해라


[더 할 것]
- immutable object : Object.freeze


[참고자료]
- poiemaweb, block-level scope : http://poiemaweb.com/es6-block-scope




댓글