신입 개발자에서 시니어 개발자가 되기까지

Cannot access before initialization 오류(feat. TDZ) 본문

error & solution

Cannot access before initialization 오류(feat. TDZ)

Jin.K 2022. 10. 27. 22:25

1.변수를 참조하고 있는 함수를 변수 선언보다 먼저 호출했을 때.

초기화 이전에 접근을 했다는 오류는 변수 선언보다 앞에서 변수를 참조하면 흔히 볼 수 있는 에러다. 근데 함수를 사용하면서 전역변수를 참조했는데,(인자로 전달해야 하지만, 깜빡하고 그냥 했다가 오류를 마주했다) 이 에러가 발생했다.


const input = require("fs").readFileSync("example.txt").toString().trim();
let triangle = input.split("\n");
for (let i = 0; i < triangle.length - 1; i++) {
  makeArray(triangle[i]);
}
let newArr = [];
function makeArray(string) {
  let array = string.split(" ").map(Number);
  newArr.push(array);
}
console.log(newArr);

왜인가 하고 봤더니, for문이 newArr보다 먼저있어서, 함수를 호출했던 것이었다.
궁금한것은, javascript는 렉시컬 스코프를 따르고, 렉시컬 스코프는 함수 평가시점에 스코프를 생성하는데 왜 참조가 안되는 것인가..?

후… 또 기초가 부족한 것 같아서 다시 책봤다.

2. let 키워드의 생명주기

1) 선언단계

-런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 실행되고, 초기화 단계는 변수 선언문에 도달했을 때 실행된다.

2) 일시적 사각지대(TDZ)

-스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없는 구간을 의미한다.

3) 1번에서 에러 발생의 이유

-1번에서 에러가 발생했던 이유는 코드의 실행이 변수 선언문에 도달하기 전에 변수에 접근했기 때문이다. (선언은 되어있는 상태다. 만약 let newArr을 지워보면 not defined 에러가 발생한다)

4) var와 비교

-var는 런타임 이전에 초기화단계까지 실행하기 때문에 다음과 같이 cannot read properties 에러가 발생한다.

3. var로 선언했을 때 오류

Cannot read properties of undefined (reading 'push')

이 때는 initialization 오류가 발생하지 않고 undefined 오류가 발생한다. var는 선언단계, 초기화단계를 함께 거치기 때문에 초기화가 이미 진행되어 있어 undefined가 할당되어있고, 여기에 psuh로 접근해서 그런 것이다. 한 마디로 호이스팅 되어 있는 상태.

javascript Deep Dive에서도 나왔듯이, 변수에 값을 할당하는 것은 코드의 실행이 변수까지 도달했을 때 그 때 이루어진다. 그래서 makeArray를 호출하는 시점에는 변수가 할당되어 있지 않다.