Skip to content

Instantly share code, notes, and snippets.

@LeoHeo
Last active February 13, 2024 08:21
Show Gist options
  • Save LeoHeo/7c2a2a6dbcf80becaaa1e61e90091e5d to your computer and use it in GitHub Desktop.
Save LeoHeo/7c2a2a6dbcf80becaaa1e61e90091e5d to your computer and use it in GitHub Desktop.
javascript var, let, const 차이점

var, let, const 차이점은?

  • varfunction-scoped이고, let, constblock-scoped입니다.

  • function-scopedblock-scoped가 무슨말이냐?

var(function-scoped)

jsfiddle 참고주소

// var는 function-scope이기 때문에 for문이 끝난다음에 i를 호출하면 값이 출력이 잘 된다.
// 이건 var가 hoisting이 되었기 때문이다.
for(var j=0; j<10; j++) {
  console.log('j', j)
}
console.log('after loop j is ', j) // after loop j is 10


// 아래의 경우에는 에러가 발생한다.
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을 만들어서 호출해야 할까? 그건 아니다.

javascript에서는 immediately-invoked function expression (or IIFE, pronounced "iffy")라는것이 있다.

IIFEfunction-scope인거 처럼 만들 수가 있다.

// IIFE를 사용하면
// i is not defined가 뜬다.
(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

근데 javascript는 여기서 좀 웃긴 부분이 있다.

위에서 잠깐 말했지만 IIFEfunction-scope처럼 보이게 만들어주지만 결과가 같지는 않다.

// 이 코드를 실행하면 에러없이 after loop i is 10이 호출된다.
(function() {
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // after loop i is 10

위에 코드가 아무 에러 없이 실행되는 이유는 i가 hoisting이 되어서 global variable이 되었기 때문이다.

그래서 아래와 같이 된 것이다.

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

IIFE는 쓰는데 이렇게 hoisting이 된다면 무슨 소용이 있겠는가?!

그래서 이런 hoisting을 막기 위해 use strict를 사용한다.

// 아까랑 다르게 실행하면 i is not defined라는 에러가 발생한다.
(function() {
  'use strict'
  for(i=0; i<10; i++) {
    console.log('i', i)
  }
})()
console.log('after loop i is', i) // ReferenceError: i is not defined

어떤가? 뭔가 변수 선언때문에 너무 많은 일을 한다고 생각하지 않는가?

그럼 let, const에 대해서 알아보자.

let, const(block-scoped)

  • es2015에서는 let, const가 추가 되었다.

javascipt에는 그동안 var만 존재했기 때문에 아래와 같은 문제가 있었다.

// 이미 만들어진 변수이름으로 재선언했는데 아무런 문제가 발생하지 않는다.
var a = 'test'
var a = 'test2'

// hoisting으로 인해 ReferenceError에러가 안난다.
c = 'test'
var c

위와 같은 문제점으로 인해 javascript를 욕 하는 사람이 참 많았다.

하지만 let, const를 사용하면 var를 사용할때보다 상당히 이점이 많다.

두개의 공통점은 var와 다르게 변수 재선언 불가능이다.

letconst의 차이점은 변수의 immutable여부이다.

let은 변수에 재할당이 가능하지만,

const는 변수 재선언, 재할당 모두 불가능하다.

// let
let a = 'test'
let a = 'test2' // Uncaught SyntaxError: Identifier 'a' has already been declared
a = 'test3'     // 가능

// const
const b = 'test'
const b = 'test2' // Uncaught SyntaxError: Identifier 'a' has already been declared
b = 'test3'    // Uncaught TypeError:Assignment to constant variable.

let, const가 hoisting이 발생하지 않는건 아니다.

varfunction-scoped로 hoisting이 되었다면

let, constblock-scoped단위로 hoisting이 일어나는데

c = 'test' // ReferenceError: c is not defined
let c

위에 코드에서 ReferenceError가 발생한 이유는 tdz(temporal dead zone)때문이다.

let은 값을 할당하기전에 변수가 선언 되어있어야 하는데 그렇지 않기 때문에 에러가 난다.

이건 const도 마찬가지인데 좀 더 엄격하다.

// let은 선언하고 나중에 값을 할당이 가능하지만
let dd
dd = 'test'

// const 선언과 동시에 값을 할당 해야한다.
const aa // Missing initializer in const declaration

이렇게 javascript에 tdz가 필요한 이유는 동적언어이다 보니깐 runtime type check 가 필요해서이다.

Reference

@chomookun
Copy link

chomookun commented Feb 23, 2020

아.. 제가 잘못본듯.ㅋ

@TuenTuenna
Copy link

명쾌한 설명에 무릎을 탁! 치고 갑니다 ㅎㅎ

@j3470
Copy link

j3470 commented Mar 25, 2020

군더더기 없이 깔-끔합니다. 덕분에 확실히 알고 갑니다. 감사... 압도적 감사! ㅎㅎ..

@ilgwonPark2
Copy link

감사히 잘 읽었습니다!
핵심이 잘 녹아져있어요

@haerang94
Copy link

잘 읽었습니다

@atelier2430
Copy link

막연하게 떠다니던 개념이 잡혔어요 감사합니다!

@AnneMayor
Copy link

깔끔하게 정리 잘하셔서 이해하기 쉬웠습니다
감사합니다

@Kibmer
Copy link

Kibmer commented Sep 10, 2020

잘봤습니다~

@YoungHaKim7
Copy link

감사합니다. 너무 너무 잘 이해 됐습니다. 정리 너무 좋습니다.

@hyunsoojin
Copy link

감사합니다~

@hyun031916
Copy link

좋은 설명 감사합니다~ 이해가 잘 되었어요!

@SEUNGHYEOK1992
Copy link

좋은 설명 감사합니다.ㅠㅠ

@SunggukCho
Copy link

예시와 설명이 너무 깔끔하네요
감사합니다!

@LEE-YONG-UN
Copy link

LEE-YONG-UN commented Jun 4, 2021

감사합니다. 도움되었습니다!

@leobang17
Copy link

감사합니다 설명 깔끔하네요.

@overnew
Copy link

overnew commented Jul 28, 2021

깔끔한 설명 감사드립니다.

@dinggididudara
Copy link

👍

@YounglanHong
Copy link

명쾌한 설명 감사합니다. 덕분에 TDZ에 대해서도 이해했어요:)

@moungJae
Copy link

감사합니다!

@SeoSangmin
Copy link

좋은 글 감사합니다!

@younho9
Copy link

younho9 commented Dec 31, 2021

// 이 코드를 실행하면 에러없이 after loop i is 10이 호출된다.

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

위에 코드가 아무 에러 없이 실행되는 이유는 i가 hoisting이 되어서 global variable이 되었기 때문이다.
그래서 아래와 같이 된 것이다.

여기 부분은 i가 hoisting 되어서 global variable이 되었다기보다 키워드 없이 선언된 변수는 암시적으로 전역 객체에 프로퍼티로 할당되기 때문인 것 같습니다.

function fn() {
    foo = 123; // window.i = 123 과 동일
}

fn();
console.log(foo); // 123

@PARKGAIN
Copy link

글 잘보고 갑니다 감사합니다!

@ChaeJiHyeon
Copy link

감사합니다

@Rayched
Copy link

Rayched commented Jul 24, 2023

좋은 글 감사합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment