TIL/JavaScript

[ECMASciprt6+ Features] 4. let & const

Art Rudy
반응형

let & const

let은 블록 범위이며 재할당은 가능하지만 재선언은 불가능하다.
function test() { 
    let let_ = "test_let_"; 
    let_ = "test_let_reassignment"; 
    // let let_ = "test_let_2"; // SyntaxError: Identifier 'let_' has already been declared 

    if (true) { 
        let let_ = "if_let_"; 
        console.log(let_); // if_let_ 
    } 
    console.log(let_); // test_let_reassignment 
} 
test();

 

결과 출력

> if_let
> test_let_reassignment

 

 

var의 이슈를 let이 해결
const var_function = function () {
    for (var i = 0; i < 3; i++) {
        setTimeout(function () {
            console.log(i); // 3, 3, 3
        }, 100);
    }
}
var_function();

 

결과 출력

3
3
3

 

var를 사용한 경우, i값이 setTimout 함수가 호출되는 시점에 이미 3이 되어있기 때문에 3이 반환된다.
즉, setTimout 함수 실행을 명령하는 시점과 반환 값이 리턴되는 시점이 달라서 i값이 명령 시점의 값으로 보장되지 않는다.
 
하지만 let을 사용할 경우, setTimout 함수 실행을 명령하는 시점의 i값과 반환 값이 리턴되는 시점의 i값을 동일할 수 있도록 보장한다.
const let_function = function () { 
    for (let i = 0; i < 3; i++) { 
        setTimeout(function () { 
            console.log(i); // 0, 1, 2
        }, 100); 
    } 
} 
let_function();

 

결과 출력

0
1
2

 

var를 쓰는 경우에도 이와 같은 결과를 보장하는 방법이 있다.
함수 실행을 명령하는 시점의 i값을 인자로 전달하여 반환 값이 리턴되는 시점의 i값을 보장할 수 있다.
const var_param_function = function () { 
    for (var i = 0; i < 3; i++) { 
        (function (i) { 
            setTimeout(function () { 
                console.log(i); // 0, 1, 2
            }, 100); 
        }(i)); 
    } 
} 
var_param_function();

 

결과 출력

0
1
2
 
let은 블록 범위이다. 따라서 for문 안의 setTimeout 함수가 참조하는 i는 같은 범위가 아닌 각각의 루프마다 다른 블록의 범위를 가지고 있다. 때문에 각각의 루프에서 호출되도록 예약된 i의 값이 공유되지 않고 명령된 시점의 i값을 보장할 수 있는 것이다.

 

const는 블록 범위이며 값이 지정되면 나중에 바꿀 수 없다. 또한, 재선언 될 수도 없다.
const const_ = "value"; 
const_ = "changed_value";  // Error
 
const는 반드시 선언과 동시에 할당이 이루어져야 한다
const const_; // SyntaxError: Missing initializer in const declaration
 
constlet과 마찬가지로 블록 레벨 스코프를 갖는다.
{
  const const_ = 10;
  console.log(const_); //10
}
console.log(const_); // ReferenceError: const_ is not defined
 
const가 한번 할당 되면 '재선언', '재할당'은 될 수 없지만 객체의 내용은 변경 가능하다.
const user = { name: 'Lee' }; 

console.log(user); // { name: 'Lee' }
// const 변수는 재할당이 금지된다. 
// user = {}; // TypeError: Assignment to constant variable. 
// 객체의 내용은 변경할 수 있다. 
user.name = 'Kim'; 
console.log(user); // { name: 'Kim' }
const 변수의 타입이 객체인 경우, 객체에 대한 참조를 변경하지 못한다는 것을 의미한다. 하지만 이때 객체의 프로퍼티는 보호되지 않는다. 다시 말하자면 재할당은 불가능하지만 할당된 객체의 내용(프로퍼티의 추가, 삭제, 프로퍼티 값의 변경)은 변경할 수 있다.
 

var vs. let vs. const

변수 선언에는 기본적으로 const를 사용하고 let은 재할당이 필요한 경우에 한정해 사용하는 것이 좋다. 원시 값의 경우, 가급적 상수를 사용하는 편이 좋다. 그리고 객체를 재할당하는 경우는 생각보다 흔하지 않다. const 키워드를 사용하면 의도치 않은 재할당을 방지해 주기 때문에 보다 안전하다.
 
var와 let, 그리고 const는 다음처럼 사용하는 것을 추천한다.
 
  • ES6를 사용한다면 var 키워드는 사용하지 않는다.
  • 재할당이 필요한 경우에 한정해 let 키워드를 사용한다. 이때 변수의 스코프는 최대한 좁게 만든다.
  • 변경이 발생하지 않는(재할당이 필요 없는 상수) 원시 값과 객체에는 const 키워드를 사용한다. const 키워드는 재할당을 금지하므로 var, let 보다 안전하다.
 
변수를 선언하는 시점에는 재할당이 필요할지 잘 모르는 경우가 많다. 그리고 객체는 의외로 재할당을 하는 경우가 드물다. 따라서 변수를 선언할 때에는 일단 const 키워드를 사용하도록 하자. 반드시 재할당이 필요하다면(반드시 재할당이 필요한지 생각해보아야 한다.) 그때 const를 let 키워드로 변경해도 결코 늦지 않는다.
반응형