유효공간, 허용공간, 살아있는 공간 등 내가 영향을 미칠수 있는 영역이라고 볼 수 있다. 이 스코프를 벗어나면 나의 영향력은 끝이난다.
자바스크립트에서 스코프를 알아보자.
ES6이전의 자바스크립트에서는 함수 스코프
만이 존재했다.
함수 스코프란 함수에 의해서 생기는 유효범위이다.
무엇의 유효범위냐 라고 한다면, 변수의 유효범위라고 할 수 있다.
if(true) {
var temp = 'function scope';
}
console.log(temp); // <- 'function scope' 출력
위 코드에서 temp
의 유효범위는 어디일까?
var
라는 키워드를 사용하여 변수를 생성하면 function scope
영역을 가지게 된다. 조건문안에 선언된 temp
를 조건문 밖에서 호출하더라도 같은 함수
내에 있기 때문에 temp의 내용이 출력된다.
함수 스코프에서는 지역변수라는 개념이 조금 애매해서 불편한점이 많았다. 그래서 ES6에서 block scope
개념이 나오게 되었다.
블록 스코프란 { }
이 중괄호를 기준으로 스코프 영역을 생성한다.
if(true) {
let temp = 'block scope';
}
console.log(temp); // temp를 찾지못하는 에러가 발생
위 처럼
let
을 이용하여 변수를 선언하면 해당 변수는 block scope
의 영향을 받는다. 그래서 조건문 안에서 선언된 temp
변수는 조건문의 블록스코프 안에서만 영향을 가질 수 있다. 조건문 밖에서 콘솔을 찍어보면 위처럼 레퍼런스 에러가 발생하게 된다.
앞에서 작성했던 호이스팅게시물은 ES5 기준으로 작성하였다.
그래서 함수 스코프만이 존재하였지만, ES6이후에 블록 스코프가 생겼다. 이때 호이스팅이 어떻게 일어날까? 아래의 코드를 보자.
if(true) {
let a = 10;
if(true) {
console.log(a); // 여기서 a는 어떻게 찍힐까???
const a = 20;
}
console.log(a);
}
console.log(a);
위에서 주석이 적혀있는곳의 a
는 무엇이 나올까?
const a
를 수집하기 때문에 undefined
가 나올것이고,
outerEnvironmentReferemce
에 있는 let a = 10
을 참조하여 10
을 출력할것이다.
그런데, 결과를 보면
ReferenceError
가 발생한다.
TDZ는 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 뜻한다. 그리고, 이 시점에서는 해당 변수를 사용할 수 없게 하였다.
여기서 자바스크림트의 변수가 어떻게 생성되는지 잠시 본다면,
1. 선언단계 (Declaration phase) : 현재 실행 컨텍스트
에서 environmentRecord
에 변수를 등록하는 단계이다. 이것을 추상적으로 호이스팅
이라고 한다.
2. 초기화단계 (Initializtion phase) : 변수의 저장공간을 메모리에 만드는 단계다. 이때 undefined
로 초기화가 된다.
3. 할당단계 (Assignment phase) : 변수에 사용자가 값을 할당하는 단계이다.
위의 3가지 단계를 거쳐 만들어지는게 변수이다.
그런데, var
와 let, const
는 생성되는 라이프사이클의 순서가 다르다.
var
의 라이프 사이클
var
키워드는 위처럼 선언과 초기화가 같이 일어난다.
그래서 선언만 하고도 콘솔에 확인을 하면undefined
가 할당되어져 있다.이말은, 변수가 선언되고 초기화 전까지 생기는
TDZ
존이 존재하지 않는다. 그래서 변수를 선언전에 호출을 하더라도호이스팅
으로 인하여undefiend
로 호출이 된다.
let
의 라이프 사이클
let
키워드는 선언과 초기화 할당이 다 분리되어 일어난다.
그래서 변수를 선언하기전에 해당 변수를 호출했을때 실행컨텍스트가 변수를호이스팅 하지만
초기화가 안되어있기에,TDZ
로 인식된다. 그래서 에러가 발생이되는데, 여기서호이스팅이 일어나지 않는다
라고 생각할수도 있지만,호이스팅은 일어난다!
일어나지만,TDZ
에 의해서 에러가 발생할 뿐이다.Reference Error
.. 레퍼런스란 무엇인가?참조
이다. 참조한다는것은메모리의 주소
를 참조한다는것이다. 메모리의 영역이 만들어지는 시점이초기화 단계
에서 일어남으로 아직 메모리 영역이 확보가 안된 상태에서 호출을하니 참조에러가 발생하는것이다.
ES6에서의 방향성이 보이는게, 원래라면 암묵적이게 일어나거나 암기해야될 것들을 최대한 배제하자라는 철학을 가진것으로 보인다.