[ydkjsy]Scope & Closures-2-Illustrating Lexical Scope

Marbles, and Buckets, and Bubbles... Oh My!


사실 BLUE의 studentID는 implied Scope로 정확하게 BLUE 스코프가 아니다.
그리고 여기서 스코프들끼리 포함관계에 있다.(red(blue(green)))) 또, 주의할 점은 여기서 색은 접근가능 여부에 따른 것이 아니라, 어디에 선언되었는지를 나타낸 것.(9,10번 줄 참고)
선언이 아닌 변수/식별자에 대한 참조는 현재 혹은 바깥에 있는 것은 가능하지만, 반대는 안된다.

보통 컴파일 중 대부분의 색이 결정이 되어 실행시 불필요한 lookup을 피하기 위해 각 범위에 대한 참조가 저장된다. 하지만 lookup을 좀 쉽게 이해하기 위해 런타임 중 9번째 줄의 students가 비선언으로 색이 없다고 가정해보자. 우선 현재 scope에서 match되는 이름이 있는지 확인하고 있으면 그 색으로 지정, 없으면 바깥 scope로 가서 찾고.. 반복.

A Conversation Among Friends

우선 컴파일러가 토큰화 진행.
1. var students 컴파일러는 스코프 매니저에게 특정 스코프에 매치되는 것이 존재하는지 물어보고, 그렇다면 무시하고 선언, 아니라면 실행시에 스코프 매니저에게 해당 범위에 새 변수를 만들 것을 요청하는 코드 작성.
2. 컴파일러는 나중에 엔진이 students = [] 할당을 처리하기 위해 실행할 수 있는 코드를 생성. 엔진이 실행할 코드는 먼저 스코프 매니저에게 현재 스코프에 접근가능한 students가 있는지 물어본다.없으면 엔진은 계속 찾아나서고 그리고 찾았다면 배열을 참조하여 할당 완성.

위를 대화체로 쓰면

Compiler: 글로벌 스코프 매니저! students 선언할건데, 본 적 있어?
Global Scope Manager: 놉, 만들었어.
Compiler: 글로벌 스코프 매니저! getStudentName 선언할건데, 본 적 있어?
Global Scope Manager: 놉, 만들었어.
Compiler: 스코프 매니저! getStudentName이 함수 가리키는데 새로운 scope이 필요해.
Function Scope Manager: 여기.
...

실행이 시작되면

Engine: 글로벌 스코프 매니저! 시작하기 전에 getStudentName 내가 여기에 함수 할당하려고 하는데 조회 가능?
(Global) Scope Manager: 응 여기 변수.
Engine: 스코프 매니저! students 타겟 참조 찾았는데 본 적 있어?
(Global) Scope Manager: 응 이 스코프에 있어. 여기.
Engine: 오 undefined로 초기화해야지. 사용할 준비가 됐어.
소스 참조 getStudentName 찾았는데, 본 적 있어?
(Global) Scope Manager: 응 이 스코프에 있어. 여기.
Engine: 이 값은 함수네. 실행해야겠다.
스코프 매니저 이 함수의 스코프 인스턴스화 해야해.

Nested Scope

각 스코프들은 스코프가 실행될 때마다 스코프 매니저 인스턴스를 가진다. 그럼 각 스코프들은 자동으로 실행하고 있는 스코프의 상단부에 모든 식별자들을 등록하는데 이것을 변수 호이스팅이라고 한다. 이 때, 함수 선언으로부터 온 식별자들은 자동으로 연관된 함수 참조로 초기화되고, var 선언으로부터 온 것들을 let/const와는 다르게 undefined로 초기화 된다.그리고 나머지 초기화되지 않은(TDZ)것들은 전체 선언-초기화가 실행되기 전까지 사용될 수 없다.

for문의 students 처리 과정.

Engine: 함수 스코프 매니저, 나 소스 참조 students 찾았는데 본 적 있?
(Function) Scope Manager: 아니. 바깥으로 가봐
Engine: 글로벌 스코프 매니저, students 봄?
(Global) Scope Manager: 응, 여기.

Lookup Failures

엔진이 확인할 스코프가 더 없다면 에러가 나는데 모드와 변수의 역할에 따라 또 다르다.

Undefined Mess

변수가 소스, 조회 실패. 선언되지 않았다고 여기고 ReferenceError.
변수가 타겟, 엄격모드, 마찬가지로 비선언 취급. ReferenceError.
is not defined 와 undefined는 다르다.
전자는 선언 자체가 되지 않은 상태. 후자는 변수는 있지만 value가 없음.
typeof 쓰면 둘다 undefined 나옴.

Global... What!?

변수가 타겟.비엄격모드.글로벌 스코프 매니저가 변수 할당을 완수하기 위해 갑자기 전역 변수를 만들 수도 있다.

function getStudentName() {
    // assignment to an undeclared variable :(
    nextStudent = "Suzy";
}

getStudentName();

console.log(nextStudent);
// "Suzy" -- oops, an accidental-global variable!

Engine: 함수 스코프 매니저! nextStudent 타겟 참조 찾았는데 본 적 있?
(Function) Scope Manager: 놉, 바깥으로 가봐
Engine: 글로벌 스코프 매니저, 본 적 있어?
(Global) Scope Manager: 놉, 하지만 지금 엄격모드가 아니라서 내가 전역 변수 만들어 줄게 여기!

엄격모드

(Global) Scope Manager: 놉. ReferenceError

좋은 웹페이지 즐겨찾기