Learn Scope & Hoisting

Junghan Lee·2023년 3월 19일
0

Learnd in Camp

목록 보기
10/48

INDEX

스코프

  • 전역 스코프
  • 지역 스코프

호이스팅


Scope

Scope는 프로그래밍에서 변수와 함수의 접근가능한 범위를 나타낸다. 간단히 말하면 스코프는 변수나 함수가 어디서부터 어디까지 유효한지를 결정한다.
변수의 스코프는 해당 변수가 선언된 위치에서부터 그 변수가 포함된 블록({})내부이며, 함수의 스코프는 함수가 선언된 위치와 함수 내부에서 선언된 변수의 스코프를 포함한다.
스코프는 변수나 함수의 이름이 충돌하지 않도록 하고, 코드의 가독성을 높이기 위해 중요하다.

여기서 파란 박스는 전역 스코프 공간,
붉은 박스는 지역 스코프 공간이다.
또한 변수 x는 지역 스코프에서 참조가 가능하며
변수 y는 전역 스코프에서 참조가 불가능한 지역 변수다.

지역 스코프의 생성 종류
함수 레벨 스코프

함수를 실행할 때 생겨나는 지역 스코프, 해당 지역 스코프에만 존재, 여기서 비롯되는 var 키워드의 문제(호이스팅)를 해결하기 위해 let, const가 등장했다.

블록 레벨 스코프

코드 블록에 의해 생성되는 스코프로
if, for, while 등 중괄호를 사용해 코드블록을 작성하는 환경에서 생성된다.
for 문 내에 a, b 변수가 존재한다.
if 내부에도 a라는 변수가 있다.
let은 재선언이 안되는데? => for(블록 레벨 스코프), if는 서로 다른 영역이므로 서로 영향을 주지 않는다.

  • 함수 또한 코드 블록이 생기고 함수의 스코프에도 영향을 받는다
    for 블록 스코프와 if 블록 스코프가 다른데 왜 에러가 나지 않을까?
    if 문에 생성된 블록 스코프 내에 a라는 변수는 존재하지 않음에도 불구하고 정상적으로 for 블록 스코프에 존재하는 a 변수를 참조하는 이유가 뭘까?

    스코프 체이닝 때문이다. JS는 변수를 참조하는 코드를 만나면 먼저 해당하는 블록 스코프 내에서 변수 참조를 시도하고 없을 때는 상위 스코프로 올라가 다시 참조한다. 따라서 if의 블록에 a라는 변수가 없어도 에러가 발생하지 않는다.

그럼 여기서 호이스팅은 뭘까?

호이스팅

Javascript 에서 함수, 변수의 선언이 위로 끌어올려진 것처럼 동작하는 것을 의미한다.
이는 JavaScript에서 코드를 해석하고 실행하는 과정에서 내부 변수의 선언, 할당 과정 때문에 발생한다.
JavaScript 는 코드를 실행하기 전에 먼저 선언된 변수, 함수 등을 전역 환경에 담아두고 이후에 정리된 코드를 실행하는 과정을 수행한다.
변수 선언의 관점 : 선언된 변수, 함수를 전역 환경에 담아두는 시기에 선언 단계라는 과정.
var, 함수 선언식에서 호이스팅이 발생한다(let,const,화살표함수,표현식에선 발생하지 않는다.)

변수의 선언 단계

초기화 돤계 이후 해당 변수에 임시 메모리 공간을 할당하고 부여된 메모리가 존재하나 값은 존재하지 않는 undefined가 담기게 된다.
초기화 단계 : JavaScript 가 실제로 코드를 실행할 때 해당 변수의 선언 코드를 만나면 수행
let, const 는 호이스팅이 발생하지 않는 것처럼 동작하나 사실은 호이스팅이 발생한다. 이는 JavaScript 가 코드실행 이전에 선언단계를 거치기 때문이다.

TDZ(Temporal Dead Zone;JS에서 변수가 선언된 위치에서부터 초기화될 때까지 접근이 불가능한 상태, TDZ가 발생하면 해당 변수를 사용하면 ReferenceError가 발생하므로 이를 피하기 위해서는 변수를 사용하기 전에 반드시 먼저 선언하고 초기화해야 한다.

console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;//에러 발생(선언 후 참조시 에러 발생안함)

)데이터가 할당되기 전,
let, const가 선언 코드를 만나기 전에 참조를 시도-> 에러 발생 이유

let, const는 선언 단계, 초기화 단계가 분리되어 실행되는데 그 사이에 TDZ가 존재한다.
반면
var 키워드는 선언, 초기화 단계가 함께 이루어져 에러가 발생하지 않는다.

변수를 변수명들이 담기는 전역 객체에 담아주는 과정과 해당 변수에 메모리 공간을 할당해주는 과정을 함께 수행
-> JS가 선언된 변수와 함수를 미리 정리하는 과정에서 이미 임시 메모리를 할당받는다. -> 참조에러가 아닌 undefined를 할당받게 된다(함수도 마찬가지)
익명 함수를 할당하는 함수 표현식은 TDZ의 영향을 받기 때문에 호이스팅이 발생하지 않는 것처럼 동작한다.
선언 키워드가 없는 함수 선언식은 TDZ의 영향을 받지 않고 호이스팅의 영향을 받게 되어 함수 선언식의 경우 undefined가 할당되는 것도 아니고 함수 그 자체가 끌어 올려진 것처럼 동작한다.

profile
Strive for greatness

0개의 댓글