변수는 let
, const
(ES6 에 도입), var
가 있다.
var
는 한 번 선언된 변수를 다시 선언할 수 있다.
var name = 'mike';
console.log(name); // "mike"
var name = 'jane';
console.log(name); // "jane"
let
은 한 번 선언된 변수를 다시 선언할 수 없다.
let name = 'mike';
console.log(name); // "mike"
let name = 'jane';
console.log(name); // error!
//Uncaught SyntaxError: Identifier 'name' has already been declared
❓ var
가 에러를 일으키지 않은 이유는?
console.log(name); // undefined
var name = 'mike';
var
는 아래와 같이 동작하기 때문이다.
var name ;
console.log(name); // undefined
name = 'mike';
var
로 선언한 모든 변수는 코드가 실제로 이동하지 않지만 최상위로 끌어 올려진 것처럼 동작한다. 이를 호이스팅(hoisting)
이라고 한다.
console.log 값이 undefined 가 출력되는 이유는 선언
은 호이스팅 되지만 할당
은 호이스팅이 되지 않기 때문이다. 할당
은 세번째 줄(위의 예제에서 name = 'mike';) 에서 처리된다.
같은 상황에서 let
은 에러가 난다.
❓ let
이 에러가 나는 이유는?
console.log(name);
let name = 'mike';
// Uncaught ReferenceError: Cannot access 'name' before initialization
let
과 const
도 호이스팅*이 된다.
호이스팅*
스코프 내부 어디에서든 변수 선언은 최상위에 선언된 것 처럼 행동하는 것을 말한다.
그런데 왜 에러가 날까.
TDZ(Temporal Dead Zone)
때문이다.
console.log(name); // Temporal Dead Zone
let name = 'mike'; // 함수 선언 및 할당
console.log(name); // 사용 가능
TDZ
영역에 있는 변수들은 사용을 할 수 없다.
let
과 const
는 TDZ
에 영향을 받는다.
할당을 하기 전에는 사용할 수 없다.
이는 코드를 예측 가능하게 하고 잠재적인 버그를 줄일 수 있다.
다른 예제를 살펴 보자.
let age = 30;
function showAge() {
console.log(age); // 30
}
showAge ();
호이스팅은 스코프* 단위로 일어난다. 여기에서 스코프* 는 함수의 내부 를 말한다.
let
으로 선언한 두 번째 age 가 호이스팅이 되면서 에러를 발생한다.
만약, 호이스팅이 발생하지 않았다면 함수 바깥에서 선언한 age 30 이 정상적으로 출력되었을 것이다.
let age = 30;
function showAge() {
console.log(age);
//Uncaught ReferenceError: Cannot access 'age' before initialization
let age = 20;
}
showAge ();
초기화 : undefined 를 할당 해 주는 단계
호이스팅 되면서 선언 단계가 이루어지지만 초기화 단계는 실졔 코드에 도달했을 때 이루어지기 때문에 ReferenceError가 발생한다.
let
과 var
는 나중에 값을 바꿀 수 있기 때문에 선언만 해 두고 나중에 할당하는 것을 허용하지만 const
는 불가하다.
아래의 예제에서는 let
과 var
는 에러가 발생하지 않지만, const
gender 는 선언과 동시에 할당을 하지 않아 에러가 발생한다.
let name;
name = 'mike';
console.log(name); // "mike"
var age;
age = 30;
console.log(age); // 30
const gender;
gender = 'male';
console.log(gender);
// Uncaught SyntaxError: Missing initializer in const declaration
함수 스코프(function-scoped) | 블록 스코프(block-scoped) |
---|---|
var | let, const |
함수 스코프(function-scoped)
함수 내에서만 선언된 변수만 그 지역 변수
가 된다.
블록 스코프(block-scoped)
모든 코드블록에서 선언된 변수는 코드블록 내에서만 유효하며 외부에서는 접근할 수 없다.
코드 블록 내에서 선언된 변수는 지역 변수
이다.
여기에서 말하는 코드 블록은 함수
, if문
, for문
, while문
, try/catch문
등을 의미한다.