var, let, const
Scope
function-scoped | var |
block-scoped | let, const |
여기서 scope라는 말은 선언된 어떤 변수가 있다면 이 변수가 유효한 공간적 범위를 말한다. 자바스크립트에서는 크게 전역스코프와 함수스코프가 존재했었고, { ECMA6부터 블록스코프(중괄호스코프)를 지원한다. } => let, const
var(function-scoped)
// 아래의 경우는 스코프안에 가두었기 때문에 에러가 발생한다
function counter() {
for(var i = 0; i < 10; i++){
console.log('i', i);
}
}
counter()
console.log('after loop i is', i); // ReferenceError: i is not defined
그렇다면 항상 function을 만들어서 호출해야 하는 것인가?
다음은 immediately-invoked function expression ( or IIFE, pronounced 'iffy')
IIFE 로 function-scope 인 것 처럼 만드는 코드다.
(function(){
// var 변수는 여기까지 hoisting
for ( var i = 0; i < 10; i++ ){
console.log('i', i)
}
})()
console.log('after loop i is', i ) // ReferenceError : i is not defined
그렇다면 다시 아래 코드를 봐보자
(function(){
for ( i = 0; i < 10; i++ ){
console.log('i', i)
}
})()
console.log('after loop i is', i) // after loop i is 10
위 코드는 에러없이 after loop i is 10이 호출된다. 왜 그럴까? IIFE를 사용해서 function-scope 처럼 보이게 해주었지만 결과는 다르다. 그 이유는 i 변수 값이 hoisting이 되어 global variable이 되었기 때문이다. 그래서 아래 코드처럼 된것이다.
var i
(function() {
for ( i = 0; i < 10; i++ ) {
.
.
.
IIFE 를 사용하는데 이렇게 hoisting이 된다면 function-scoped 에 의미가 없다.
그래서 이런 hoisting을 막기 위해 use strict 을 사용한다.
(function() {
'use strict'
for ( i = 0; i < 10; i++ ) {
console.log('i', i);
}
})()
consoel.log('after loop i is', i) // ReferenceError : i is not defined
흠.. 그런데 변수 선언때문에 너무 많은 일을 하는 것 같다..
let 과 const 설명을 보자
let, const(block-scoped)
기존의 javascript 에서는 var 만 있었기 때문에 아래와 같은 문제가 있었다.
var a = 'test'
var a = 'test2'
이미 만들어진 변수이름으로 재선언 했는데 문제가 발생하지 않았고
c = 'test'
var c
hoisting으로 인해 ReferenceError가 안났다.
하지만 let, const를 사용하면 var와 다르게 변수 재선언 불가능이다.
둘의 차이점은 변수의 immutable 로 let 은 변수에 재할당이 가능하고, const 는 변수 재선언, 재할당이 모두 불가능하다.
let
const
let 과 const 가 hoisting이 발생하지 않는건 아니며 var 가 function-scoped 로 hoisting이 되었다면
let 과 const 는 block-scoped 단위로 hoisting이 일어난다.
c = 'test' // ReferenceError: c is not defined
let c
위의 코드에서 ReferenceError 가 발생한 이유는 temporal dead zone(tdz) 때문으로 let은 값을 할당하기전에 변수가 선언되어 있어야 한다. const 도 같지만 const 는 선언과 동시에 값을 할당 해야한다.
const aa = 22;
const USER_NAME; // 값을 할당하지 않을 시 에러 발생