2차 공부/TIL

24.05.30 TDZ와 Hoisting, var let const

공대탈출 2024. 5. 30. 20:59

스코프란?

스코프란 변수에 접근할 수 있는 범위를 의미하며, 자바스크립트에서는 전역과 지역스코프가 존재한다.

전역스코프란 어느 곳에서나 변수가 선언되어있어 제한없이 접근 할 수 있는 것이고,

지역스코프란 특정한 공간에 변수가 선언되어있어 변수의 접근이 제한되어 있는 것이다.

var a = 1;
function test() {
    var a = 'hi';
    console.log(a);
}
test();

console.log(a);

이러한 코드가 있다고 하자. 결과가 어떻게 출력될까?

hi가 먼저 출력되고, 1이 출력될 것이다.

test()함수의 선언 에서 a라는 변수가 'hi'로 선언 및 초기화가 되었으므로 hi를 먼저 출력한다.

그리고 console.log(a)가 실행되는데, 이때 a는 전역변수로 선언 된 1이 출력된다.


호이스팅이란?

호이스팅이란 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다.

선언 초기화
var a a = 1
let b b =2
const c c =3
- d =4

위 표와 같이 선언은 var, let, const를 사용하여 변수나 상수를 선언하는 것, 초기화는 해당 변수에 값을 넣는 것을 의미한다.

var은 선언과 동시에 초기화 하지 않더라도, undefined의 값이 자동으로 초기화 되지만, let과 const는 아무 값도 가지지 않는 TDZ를 갖는다.


TDZ란?

TDZ란 Temporal Dead Zone, 말 그대로 '시간상 사각지대'가 적절한 표현이다. 선언과 초기화 사이에 잠깐 죽은 시간대 정도로 이해하면 좋다.

 

먼저 let,const와 var의 차이를 위에서 설명한 것과 같이 알아보자.

function vartest() {
	var x = 1;
    if (true) {
    	var x = 2;
        console.log(x)
    }
    console.log(x)
}
vartest()

해당 함수를 실행하면 2가 먼저 출력되고 1이 출력된다.

var은 전역함수로 사용되지만, if문 안에서 x가 2로 선언및 초기화가 되었으므로 먼저 쓰여진 if문의 console.log인 2가 출력되고,

나중에 쓰여진 console.log는 if문에 선언된 var x의 스코프를 벗어나므로 1이 출력된다.

 

function lettest() {
	let x = 1;
    if (true) {
    	let x = 2;
        console.log(x);
    }
    console.log(x)
}

이것도 똑같이 2 후에 1이 출력된다.

if문 안에 선언된 x는 바인딩 되었으므로 외부 스코프에 영향을 끼치지 못하고, if문 밖에 선언된 x의 값을 마지막 console.log가 따른다.

 

var x = 1;
let y = 2;
console.log(this.x);
console.log(this.y);

앞서 말했듯, var로 선언된 변수는 '전역변수'이며 let으로 선언된 변수는 '지역변수'이다.

따라서 전역객체를 뜻하는 this에는 변수 x는 저장되었지만, 지역변수인 y는 저장되지 않는다.

따라서 this.x값만 출력되고, this.y값은 값이 없다고 나온다.

 

const pi = 3.14로 선언 및 초기화 되기 전에 pi에 대한 TDZ가 형성되며, 이곳에서 pi를 사용하면 reference err가 발생한다.

다시한번 말하지만, 전역변수 선언인 var은 선언과 초기화가 바로 이루어지므로 에러가 발생하지 않고, let과 const만 발생한다.

그 외에도 기본함수 매개변수, class, constructor() 내부의 super()도 TDZ를 갖는다.


따라서 변수나 함수의 사용은 TDZ를 잘 고려해야하고, 스코프를 잘 고려해야한다.

또한 전역변수를 만들어내는 var은 사용은 지양을 하고, 필요한 때에만 사용해야한다.


렉시컬스코프(Lexical Scope, 어휘적 스코프)

렉시컬 스코프란 함수를 어디에 선언하였는지에 따라 상위 스코프가 결정되는 것을 의미한다.

1번 - 전역 스코프를 감싸고 있고, 함수1만 있다.

2번 - 함수1의 스코프를 감싸고 있고, 변수 a, b와 함수2를 포함하고 있다.

3번 - 함수2의 스코프를 감싸고 있고, 변수c만을 포함하고 있다.

 

이렇게 3개의 중첩 스코프가 있다.

함수2는 함수1의 스코프 내부에 완전히 포함되는데, 이는 함수1 내부에서 함수2를 선언했기 때문이다.

 console.log()가 실행될 때 a, b, c를 검색하는데 이땐 함수2 스코프부터 시작하여 변수를 찾지 못하면 함수1스코프 그 후론 전역스코프까지 변수를 찾을때까지 올라간다.

  만약 c가 함수2나 함수1 내부에 둘 다 존재하면 함수2 내부부터 사용하고, 함수1에는 찾으러 가지 않아도 된다. 목표대상을 찾는 즉시 검색을 중단하기 때문에 중첩 스코프 층에 걸쳐 같은 변수 이름을 정의할 수 있고, 이를 새도잉이라 한다.

 어떤 함수가 어디서 호출되는지에 상관없이 함수의 렉시컬 스코프는 함수가 선언된 위치에 따라 정의된다.  함수 선언 시점에 따라 상위 스코프가 결정되기 때문에 호출은 스코프 결정에 전혀 영향을 끼치지 않는다.

 

 

 


 

 

 

let - JavaScript | MDN

let 명령문은 블록 스코프의 범위를 가지는 지역 변수를 선언하며, 선언과 동시에 임의의 값으로 초기화할 수도 있습니다.

developer.mozilla.org

 

[JavaScript] 스코프(Scope)와 클로저(Closure)

🍀 목차 글의 목적 스코프 스코프의 구분 스코프 이해 + LHS, RHS 어휘적 스코프(Lexical Scope) 함수 레벨 스코프 vs 블록 레벨 스코프 클로저 클로저 예제 글의 목적 자바스크립트를 학습하다 보면 스

youngju-js.tistory.com

 

 

렉시컬 스코프와 클로저, 그리고 커링

MDN에 클로저의 정의는 ‘함수와 함수가 선언된 어휘적 환경의 조합이다’ 라고 나타나 있다.그리고 클로저를 이해하려면 렉시컬 스코프(Lexical Scope)를 먼저 이해해야 한다고 나와있다.따라서,

velog.io

 

'2차 공부 > TIL' 카테고리의 다른 글

24.06.03 JS 톺아보기  (0) 2024.06.03
24.05.31 배열과 연결 리스트(NodeList)  (0) 2024.05.31
24.05.29 display: flex (2)  (0) 2024.05.29
24.05.28 display: flex  (0) 2024.05.28
24.05.27 React 트랙을 신청한 이유  (0) 2024.05.27