[ES6+] Block Scope & hoisting

Chipmunk_jeong·2021년 8월 8일
0

TIL

목록 보기
59/62
post-thumbnail

스코프란 무엇일까?

유효공간, 허용공간, 살아있는 공간 등 내가 영향을 미칠수 있는 영역이라고 볼 수 있다. 이 스코프를 벗어나면 나의 영향력은 끝이난다.
자바스크립트에서 스코프를 알아보자.

함수 스코프(function scope)


ES6이전의 자바스크립트에서는 함수 스코프만이 존재했다.
함수 스코프란 함수에 의해서 생기는 유효범위이다.
무엇의 유효범위냐 라고 한다면, 변수의 유효범위라고 할 수 있다.

if(true) {
  var temp = 'function scope';
}
console.log(temp); // <- 'function scope' 출력

위 코드에서 temp의 유효범위는 어디일까?
var라는 키워드를 사용하여 변수를 생성하면 function scope영역을 가지게 된다. 조건문안에 선언된 temp를 조건문 밖에서 호출하더라도 같은 함수내에 있기 때문에 temp의 내용이 출력된다.

블록 스코프(block scope)


함수 스코프에서는 지역변수라는 개념이 조금 애매해서 불편한점이 많았다. 그래서 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가 발생한다.

Temporal Dead Zone(TDZ)라고 불리는 영역이다. 번역하자면 임시사각지대 또는 일시적사각지대라고 할 수 있다.

TDZ는 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 뜻한다. 그리고, 이 시점에서는 해당 변수를 사용할 수 없게 하였다.
여기서 자바스크림트의 변수가 어떻게 생성되는지 잠시 본다면,
1. 선언단계 (Declaration phase) : 현재 실행 컨텍스트에서 environmentRecord에 변수를 등록하는 단계이다. 이것을 추상적으로 호이스팅이라고 한다.
2. 초기화단계 (Initializtion phase) : 변수의 저장공간을 메모리에 만드는 단계다. 이때 undefined로 초기화가 된다.
3. 할당단계 (Assignment phase) : 변수에 사용자가 값을 할당하는 단계이다.

위의 3가지 단계를 거쳐 만들어지는게 변수이다.
그런데, varlet, const는 생성되는 라이프사이클의 순서가 다르다.

var의 라이프 사이클


var키워드는 위처럼 선언과 초기화가 같이 일어난다.
그래서 선언만 하고도 콘솔에 확인을 하면 undefined가 할당되어져 있다. 이말은, 변수가 선언되고 초기화 전까지 생기는 TDZ존이 존재하지 않는다. 그래서 변수를 선언전에 호출을 하더라도 호이스팅으로 인하여 undefiend로 호출이 된다.

let의 라이프 사이클


let키워드는 선언과 초기화 할당이 다 분리되어 일어난다.
그래서 변수를 선언하기전에 해당 변수를 호출했을때 실행컨텍스트가 변수를 호이스팅 하지만 초기화가 안되어있기에, TDZ로 인식된다. 그래서 에러가 발생이되는데, 여기서 호이스팅이 일어나지 않는다라고 생각할수도 있지만, 호이스팅은 일어난다! 일어나지만, TDZ에 의해서 에러가 발생할 뿐이다. Reference Error.. 레퍼런스란 무엇인가? 참조이다. 참조한다는것은 메모리의 주소를 참조한다는것이다. 메모리의 영역이 만들어지는 시점이 초기화 단계에서 일어남으로 아직 메모리 영역이 확보가 안된 상태에서 호출을하니 참조에러가 발생하는것이다.

ES6에서의 방향성이 보이는게, 원래라면 암묵적이게 일어나거나 암기해야될 것들을 최대한 배제하자라는 철학을 가진것으로 보인다.

profile
Web Developer

0개의 댓글