변수는 크게 선언되는 위치에 따라 로컬(지역)변수
와 글로벌(전역)변수
로 나뉜다.
let a = 1;
function myFunction() {
console.log(a);
}
myFunction(); // 1
변수 a
는 블록 밖에 선언된 전역 변수로 함수 블록 안에서도 접근이 가능하다.
let a = 1;
function myFunction() {
let a = '하나';
console.log(a);
}
myFunction(); // '하나'
console.log(a); // 1
블록 안에서는 밖에 있는 변수와 동일한 이름의 새 변수를 선언할 수 있다.
즉, 블록 내부에 선언된 지역 변수가 있는지 확인하고 있으면 해당 지역 변수를 사용, 없으면 블록 밖에 있는 전역 변수를 사용하게 된다.
자바스크립트에는 3가지의 변수 선언 방법이 있다.
let
const
var
블록 스코프를 가진 변수
let a;
let name = '효선';
let age = 27, gender = '여성';
블록 스코프가 없는 변수
->var
로 선언한 변수의 스코프는 함수 스코프이거나 전역 스코프이다.
반복문 예시)
for (var i = 0; i < 10; i++) {
// ...
}
console.log(i); // 10 반복문이 종료되었지만 전역 스코프이므로 접근이 가능하다.
함수 스코프 예시)
function myVar() {
if(true) {
var name = '효선';
}
console.log(name);
}
myVar(); // 효선
console.log(name); // 출력되지 않는다.
값을 바꿀 수 없는 변수 선언. (상수)
const a; // SyntaxError: Missing initializer in const declaration
const BIRTHDAY = 950218;
BIRTHDAY = 931226; // TypeError: Assignment to constant variable.
window 객체는 브라우저의 요소들과 자바스크립트 엔진, 그리고 모든 변수를 담고 있는 객체이다. 글로벌 객체로 부르기도 한다.
var food = '음식';
let animal = '동물';
console.log(this.food, this.animal);// 음식, undefined
// window객체에 들어가므로 window.food 로 사용할 수도 있다.
💡 변수나 함수의 선언이 최상위로 끌어올려지는 현상, 변수가 함수 내에서 선언된 지역 변수이면 함수 내의 최상위, 글로벌 스코프에 선언된 전역 변수이면 전역 컨텍스트 최상위로 끌어올려진다.
함수 선언문 호이스팅은 따로 다룰 예정이다.
undefined
이다.console.log(food); // undefined
var food = '음식';
var 변수는 아래에 선언되어있지만 선언이 위로 끌어올려지면서 food의 값을 undefined로 출력할 수 있다.
위 코드를 풀어보면, 아래와 같이 실행된다고 볼 수 있다.
var food;
console.log(food); // undefined
food = '음식';
console.log(food); // 음식
console.log(animal); // ReferenceError
let animal = '동물';
let과 const에선 ReferenceError
가 발생한다. 이는 TDZ(Temporal Dead Zone)
에 영향을 받기 때문에 var 변수와는 다르게 작동한다.
❗ 흔히들 let과 const는 호이스팅이 되지 않는다고 생각할 수 있지만.. let과 const도 변수도 호이스팅이 된다!!!!
직역하면 일시적인 사각지대 라는 뜻인데 이 일시적인 사각지대는 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말한다.
변수 생성의 3단계
-> 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계!
이 변수 객체는 스코프가 참조하는 대상이 된다.
-> 실행 컨텍스트에 존재하는 변수 객체에 등록된 변수를 위한 메모리를 만드는 단계!
이 단계에서 변수는 undefined
로 초기화된다.
-> undefined
로 초기화된 변수에 다른 값을 할당하는 단계
📃 var 변수의 경우 선언과 초기화를 동시에 진행한다. 메모리를 할당해주고 undefined로 초기화되기 때문에 호이스팅될 때 에러가 나지 않는다.
📃 let 변수의 경우 선언과 초기화를 따로 진행한다. 선언 단계에서 변수가 등록되지만 초기화 단계는 변수 선언문에 도달했을 때 이루어지기 때문에 그 전에 변수에 접근하려하면
ReferenceError
가 발생한다. *변수를 위한 메모리 공간이 확보되지 않았기 때문.
console.log(animal); // ReferenceError
let animal; // 변수 선언문에서 초기화 단계
console.log(animal); // undefined
animal = '동물'; // 할당문에서 할당 단계
console.log(animal); // 동물
📃 const 변수의 경우 var 변수처럼 선언과 초기화를 동시 진행하지만 선언 이전에
TDZ
가 생성되어 접근하면ReferenceError
가 발생한다. 반드시 선언과 동시에 할당도 해줘야한다
취업을 하기 전 한 회사에서 면접을 보았는데 let과 const가 호이스팅이 되느냐란 질문에 안된다고 대답했었다. var변수만 된다고 대답했었다.. TDZ에 대해서도 물어보셨는데 대답을 하지 못했던 기억이 있다.... 변수는 그냥 일상 생활에서 사용하듯이(?) 써서 TDZ에 대해 깊게 다뤄보지 못했었는데 이제와 생각해보면 참 리액트 공부하는데에만 급급했구나 싶다.. 그 후에 TDZ가 뭔지 알아보았는데 이번 회사에서 동료들이랑 자바스크립트 스터디를 시작한 김에 공부한 것을 블로그에 정리하면 좋을 것 같아서 적어보았다.
그리고 결론 .... 처음 자바스크립트 공부 시작할 때 es6부터 바로 해서 var 변수는 사용한 적도 없었는데 더더욱 쓰지 말아야겠다는 생각이 들었다.