SUIN

[JS] var,let,const 의 차이점 (선언,스코프, 호이스팅) 본문

JavaScript

[JS] var,let,const 의 차이점 (선언,스코프, 호이스팅)

choi suin 2023. 3. 27. 20:33
728x90

변수 선언 기준

ES6 이전 : var , ES6 이후: let,const

 

변수 선언 방식

var: 변수 재선언 가능 , 재할당 가능

//var
var name = 'javascript';
console.log(name); // javascript

var name = 'react';
console.log(name); // react

 

동일한 변수명을 한번더 선언했음에도 불구하고 에러메세지가 없으며 이는 유연한 변수 선언으로 간단한 테스트에는 편리 할 수 있겠으나, 코드량이 많아 진다면 어디에서 어떻게 사용 될지도 파악하기 힘들뿐더러 값이 바뀔 우려가 있다.

  • 변수 중복 선언 가능하여, 의도하지 않은 변수값의 변경이 일어날 가능성이 크다.
  • 암묵적 전역 변수를 양산할 가능성이 크다.

let : 변수 재선언 불가능, 재할당 가능 

//let
let name = 'javascript';
console.log(name); // javascript

let name = 'react';
console.log(name); // Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'vue';
console.log(name); // vue

 

let은 var와 달리 중복선언 시, 해당 변수는 이미 선언되었다는 에러 메시지를 뱉는다. 즉, 중복선언이 불가하다. 하지만 변수에 값을 재할당하는 것은 가능하다.

const : 상수 재선언 불가능, 재할당 불가능

//const
const name = 'javascript';
console.log(name); // javascript

const name = 'react';
console.log(name); // Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'vue';
console.log(name); // Uncaught TypeError: Assignment to constant variable

let와 const의 차이는 immutable(재할당)가능여부

const는 반드시 선언과 동시에 할당이 이루어져야 한다 재할당은 가능한 let과 달리 const는 재할당 또한 불가하다.

 

스코프 (Scope)

대부분의 프로그래밍 언어는 블록 레벨 스코프(Block-level scope)를 따르지만 자바스크립트는 함수 레벨 스코프(Function-level scope)를 따른다.

함수 레벨 스코프(Function-level scope)

함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

블록 레벨 스코프(Block-level scope)

모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.

 

var : 함수 레벨 스코프 (function-level scope)

var foo = 123; // 전역 변수

console.log(foo); // 123

{
  var foo = 456; // 전역 변수
}

console.log(foo); // 456

블록 레벨 스코프를 따르지 않는 var 키워드의 특성 상, 코드 블록 내의 변수 foo는 전역 변수이다. 그런데 이미 전역 변수 foo가 선언되어 있다.

var 키워드를 사용하여 선언한 변수는 중복 선언이 허용되므로 위의 코드는 문법적으로 아무런 문제가 없다. 단, 코드 블록 내의 변수 foo는 전역 변수이기 때문에 전역에서 선언된 전역 변수 foo의 값 123을 새로운 값 456으로 재할당하여 덮어쓴다.

 

let, const : 블록 레벨 스코프 (block-level scope)

let foo = 123; // 전역 변수

{
  let foo = 456; // 지역 변수
  let bar = 456; // 지역 변수
}

console.log(foo); // 123
console.log(bar); // ReferenceError: bar is not defined

let 키워드로 선언된 변수는 블록 레벨 스코프를 따른다. 위 예제에서 코드 블록 내에 선언된 변수 foo는 블록 레벨 스코프를 갖는 지역 변수이다. 전역에서 선언된 변수 foo와는 다른 별개의 변수이다. 또한 변수 bar도 블록 레벨 스코프를 갖는 지역 변수이다. 따라서 전역에서는 변수 bar를 참조할 수 없다.

 

호이스팅 (Hoisting)

자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.

호이스팅(Hoisting)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성

자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다

선언 단계 > 초기화 단계 >  할당 단계

  • 선언 단계: 변수를 실행 컨텍스트의 변수 객체(Variable Object)에 등록한다. 이 변수 객체는 스코프가 참조하는 대상이 된다.
  • 초기화 단계: 변수 객체(Variable Object)에 등록된 변수를 위한 공간을 메모리에 확보한다. 이 단계에서 변수는 undefined로 초기화된다.
  • 할당 단계: undefined로 초기화된 변수에 실제 값을 할당한다

 

var : 선언 단계와 초기화 단계가 동시에 진행

// 1. 스코프의 선두에서 선언 단계+ 초기화 실행
// 변수 선언문 이전에 변수를 참조할 수 있다.
console.log(foo); //undefined

var foo
console.log(foo) //undefined

foo = 1; //2.할당
console.log(foo); // 1

스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화(초기화 단계)한다.

따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다.

이후 변수 할당문에 도달하면 비로소 값이 할당된다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라 한다.

let,const : 선언 단계와 초기화 단계가 분리되어 진행

// 1. 스코프의 선두에서 선언 단계가 실행
console.log(foo); //ReferenceError: foo is not defined 
//일시적 사각지대 (Temporal Dead Zone)

let foo //2.초기화 
console.log(foo) //undefined

foo = 1; //3.할당 
console.log(foo); // 1

변수를 위한 메모리 공간이 아직 확보되지 않았기 때문에 초기화 이전에 변수에 접근하려고 하면 참조 에러(ReferenceError)가 발생한다.

때문에 호이스팅은 발생하였으나 변수의 선언과 초기화 사이에 일시적으로 변수값을 참조할수 없는 구간인 TDZ(Temporal Dead Zone)에 빠졌기 때문에 보이는 현상

 


정리

  • 기존의 es6 이전 변수선언 var 의 문제점들이 보완된 es6- let, const 등장
  • let와 const의 차이는 immutable(재할당)가능여부
  • ES6를 사용한다면 var 키워드는 사용하지 않는다.
  • 재할당이 필요없는 상수과 객체에는 기본적으로 const를 사용( 의도치 않은 재할당을 방지해주기 때문에 안전)
  • 재할당이 필요한 경우 한정적으로 let을 사용.( 단, 이 때 변수의 스코프는 최대한 좁게 만드는 것이 좋다.)

 

var: 변수 재선언 가능 , 재할당 가능 / 호이스팅: 선언 단계와 초기화 단계가 동시에 진행

let : 변수 재선언 불가능, 재할당 가능  / 호이스팅: 선언 단계와 초기화 단계가 분리되어 진행

const : 상수 재선언 불가능, 재할당 불가능 / 호이스팅: 선언 단계와 초기화 단계가 분리되어 진행

 

var 변수의 단점

  1. 함수 레벨 스코프(Function-level scope)
    • 함수의 코드 블록만을 스코프로 인정한다. 따라서 전역 함수 외부에서 생성한 변수는 모두 전역 변수이다. 이는 전역 변수를 남발할 가능성을 높인다.
    • for 문의 변수 선언문에서 선언한 변수를 for 문의 코드 블록 외부에서 참조할 수 있다.
  2. var 키워드 생략 허용
    • 암묵적 전역 변수를 양산할 가능성이 크다.
  3. 변수 중복 선언 허용
    • 의도하지 않은 변수값의 변경이 일어날 가능성이 크다.
  4. 변수 호이스팅
    • 변수를 선언하기 이전에 참조할 수 있다.

 

 

 

 

참고 자료

https://poiemaweb.com/es6-block-scope

 

'JavaScript' 카테고리의 다른 글

[JS] 식별자란  (0) 2023.04.18
[JS] Event Loop 란?  (0) 2023.04.04
[JS] 함수형프로그래밍이란?  (0) 2023.04.04
[모던 자바스크립트] 2.2 코드구조  (0) 2021.11.24
[Javascript] .map() .filter() .reduce()  (0) 2021.11.11