Scope of var
범위는 기본적으로 변수를 사용할 수 있는 위치를 의미한다. var선언은 전역 범위 혹은 함수 범위로 지정
var변수가 함수 외부에서 선언될 때의 범위는 전역이다. 즉, 함수 블록 외부에서 var을 사용하여 선언된 모든 변수를 전체 왼도우 상에서 사용 가능. 그에 반면 var가 함수 내에서 선언될 때는 함수 범위로 지정. 즉 해당 함수 내애서만 사용하고 접근 가능//var 변수를 함수 밖에서 사용하였을때의 오류 function func(){ var hello="hello"; } console.log(hello); //error: hello is not defined.
❗️var 변수는 재선언되고, 재할당 가능
var a=10; var a=20; a=30;
블록 범위 let
블록은 {}로 바인된 코드 이다. 하나의 블록은 중괄호 속에서 존재하며, 중괄호 안에 있는 것은 모두 블록 범위 이다.
물론 블록 외에서 선언된 경우에는 전역적으로 사용 가능let times=4; let hi ="hi"; if(times>2){ let hi="bye"; console.log(hi); //bye } console.log(hi); //hi
❗️let 은 재할당은 가능하지만 재선언은 불가능 하다.
let a=10; a=20; console.log(a); //20
let b=10; let b=10; //error
❗️그러나 동일한 변수가 다른 범위 내에서 정의된다면, 에러는 발생하지 않음
let hi="hi"; if(true){ let hi="hello"; console.log(hi); //hello } console.log(hi); //hi
❗️var 과 let의 차이
var 로 선언된 변수는 선언되게 전에 출력을 하면 undefined 라고 뜬다
console.log(a); //undefined; var a=10;
하지만 let으로 선언된 변수는 선언되게 전에 출력을 하면 error라고 뜬다.
console.log(a); let a=10;
이러한 이유는 let으로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone)에 빠지기 때문이다.
변수는 크게 1.) 선언 단계 -> 2.) 초기화 단계 -> 3.) 할당 단계 에 걸쳐 생성되는데 var은 선언단계와 초기화 단계가 한번에 이루어진다.
하지만 let으로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.
변수 생명주기
- 선언 단계: 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계를 의미, 이 변수 객체는 스코프가 참조하는 대상이 된다.
- 초기화 단계: 실행 컨텍스트에 존재하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계, 이 단계에서 할당된 메모리는 undefined로 초기화 된다.
- 할당 단계: 사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계이다.
var 변수 생명 주기
생명 주기인 선언 단계 와 초기화 단계를 모두 동시에 진행
let 변수 생명 주기
생명 주기인 선언 단계 와 초기화 단계를 모두 분리 되어서 진행
❗️즉, let은 실행 컨텍스트 변수 객체에 등록이 되어 호이스팅이 되지만, 이 tdz구간에 의해 메모리가 할당이 되질 않아 참조 에러가 발생
참고로 함수 키워드 함수는 변수 선언 3단계를 동시에 진행tdz란?🤔
temporal dead zone의 약자로 우리 말로 번역하면 일시적 사작지대 라는 의미이며 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말한다. 다른 말로는 변수가 선언되고, 변수의 초기화가 이루어지기 전까지의 구간이라고 말할 수 있음.
tdz에서는 선언 되기 전이거나 초기화 되기 전인 상태의 변수를 사용하는 것을 허용하지 않음. 그래서 tdz구간 때 선언되지 않거나 초기화 전인 변수를 참조하게 되면 에러가 발생하게 됩니다.
블록범위 const
let선언처럼 const선언도 선언된 블록 범위 내에서만 접근 가능
❗️const는 업데이트도, 재선언도 불가능하다.
const a=1; a=3; console.log(a); //error; const b=2; const b=3; //error
❗️하지만 객체의 경우는 다소 다르다. const객체는 업데이트할 수 없지만, 객체의 '속성'은 업데이트 가능
const user={ name: 'andy', age: 25, }; //이러한 작업은 불가능 user={ age: 23, } //하지만 요거는 가능 user.gender="male';
let과 마찬가지로 const선언도 맨 위로 끌어올려지지만, 초기화되지는 않음
❗️세가지 변수 선언법의 차이점에 대하여 총 정리
var선언은 전역 범위 또는 함수 범위이며, let과 const는 블록 범위이다.
var변수는 범위 내에서 재할당 및 재선언이 가능하지만, let변수는 재할당만 가능하고 재선언은 불가. const변수는 업데이트와 재선언 둘 다 불가
세 가지 모두 최상위로 호이스팅된다. 하지만 var변수만 undefined으로 초기화 되고 let과 const변수는 초기화 되지 않음.
❗️var과 let은 초기화하지 않은 상태에서 선언 할수 있지만 const는 선언 중에 초기화 해야 함