Javascript var, let, const

var, let , const 의 차이점을 알아보자..!

1. scope

var는 function scoped 이고 let, const는 block-scoped 이다.

Var


변수의 범위와, hoisting 범위 모두 function

예시1

for (var i=0; i<10; i++){
  console.log('i', i)
}
console.log('after loop i', i) // 10

예시1 에서는 i가 function scoped 이기 때문에 loop가 끝난 후 i를 호출하면 출력이 잘 된다.

예시2

function example(){
  for (var i=0; i<10; i++){
  	console.log('i', i)
	}
}
example()
console.log('after loop i', i) // Reference Error: i is not defined

예시2 에서는 function scoped 밖에서 호출해서 에러가 뜬다.

위와 같은 방법을 이용해서.. 예전에는 이렇게 변수 관리를 했다고 한다.

var gVariable = (function(name){
  for (var i=0; i<10; i++){
    console.log('i', i)
  }
  console.log(name) // 'kim'
})('kim')
console.log('after loop i', i) // Reference Error: i is not defined

즉시 실행 함수를 이용하여 함수 내부의 변수를 priavte화 하고 ( scope가 function 이니까!) gVariable 는 전역변수로 사용했다고 한다.

단 여기서도 알아둬야 할 점이 있다.

var i
(function(name){
  for (i=0; i<10; i++){
    console.log('i', i)
  }
  console.log(name) // 'kim'
})('kim')
console.log('after loop i', i) // after loop i 10

예시2 에서 var 키워드를 뺀다면 위와 같이 i 가 hoisting 되어 global variable이 된다.

예전에는 이를 막기위해 아래와 같은 방법을 썻다고 한다.

(function(name){
  'use strict'
  for (i=0; i<10; i++){
    console.log('i', i)
  }
  console.log(name) // 'kim'
})('kim')
console.log('after loop i', i) // Reference Error

use strict 를 사용하여 i변수가 hoisting 되는 것을 막는다. use strict는 이처럼 hoisting을 막기도 하고, this 가 window 객체를 가리키지 못하게 한다.


let, const


변수의 범위와, hoisting 범위 모두 blocked

let 과 const 는 blocked scoped 이다. let과 const의 차이는 변수의 immutalbe 여부이다. let은 변수에 재할당이 가능하지만, const 는 변수 재선언, 재할당 모두 불가능하다.

위에서 사용했던 예시1을 비교해 보면,

for (let i=0; i<10; i++){
  console.log('i', i)
}
console.log('after loop i', i) // Reference Error

i가 blocked scoped 이기 때문에 참조 에러가 발생한다.

다른예시.

for (var i=0; i<10; i++){
  setTimeout(function(){console.log(i)}, 3000)
}

위와 같은 코드를 실행하면 i가 10으로 10번 출력된다. 그 이유는 for문이 끝나는 시점의 i 변수는 var로 선언 되었기 때문에 function scoped를 갖게 되고 해당 시점의 i값은 10이기 때문이다.

  • 해결방법1

선언을 let으로 한다면,

for (let i=0; i<10; i++){
  setTimeout(function(){console.log(i)}, 3000)
}

자바스크립트 엔진이 실행될 때 블록이 10개 생기고 각 블록의 i 값을 참조하기 때문에 올바르게 원하는 값을 출력 할 수 있다.

  • 해결방법2

위에서 정리한 즉시실행함수(IIFE)를 이용

for (var i=0; i<10; i++){
  (function(count){
    setTimeout(function(){
      console.log(count)
    },3000)
  })(i)
}

2. 중복 선언

var는 중복 선언을 허용한다

let 과 const는 중복 선언을 허용하지 않는다.

var a = 1
var a = 2 // okay
let b = 1
let b = 2 // Nooo 

3. 선언과 초기화

  • var는 변수의 선언과 동시에 undefined로 초기화가 된다.
  • let은 변수 선언 이전에 참조를 하면 Reference Error가 발생한다. 선언과 동시에 undefined로 초기화 되는 var와 다르게 let은 선언만 되고 대입 연산자를 만날 때 까지 값이 없다. 따라서 값이 할당 되기 전까지 참조를 하게 되면 Reference Error를 발생하게 되고 이 구간을 TDZ(temporal dead zone) 이라고 한다.
console.log(a) // undefined
var a = 'hi'

a 변수가 hoisting 되어 scope 상단에 선언과 동시에 undefined로 초기화 되었기 때문에 오류가 발생하지 않는다.

console.log(b) // Uncaught ReferenceError: b is not defined
let b = 'hi'

b 변수가 hoisting 되어 scope 상단에 선언 되겠지만, 값이 초기화 되지 않기 때문에 참조하려고 하면 에러를 발생시킨다.

  • const는 선언과 동시에 초기화 해줘야 한다!

Written by@[HongDongUk]
공부한 것을 소소하게 적는 블로그.

GitHubFacebook