원문 : ⚡️⛓ JavaScript Visualized: Scope (Chain)
스코프 체인을 위한 시간입니다 🕺
이 포스트는 JS의 실행 컨텍스트에 대한 기본적인 이해를 하고 있다고 가정합니다. 곧 그에 대한 글도 작성하겠습니다.😃
다음 코드를 살펴보죠!
이름
, 나이
, 도시
값 변수를 포함한 문자열을 반환하는 getPersonInfo
함수를 호출합니다.
Sarah는 22살이고 샌프란시스코에 삽니다.
하지만, getPersonInfo
함수는 city
를 포함하고 있지 않습니다. 🤨? 어떻게 이 함수는 city
값을 알고 있을까요?
먼저, 메모리 공간은 다른 컨텍스트에 대해 설정됩니다. 우리는 기본적으로 global context(브라우저의 window
, 노드의 global
)과 우리가 호출한 getPersonInfo
함수에 대한 local context를 갖고 있습니다. 또한 각 컨텍스트는 스코프 체인을 가지고 있습니다.
getPersonInfo
의 경우 스코프 체인은 아래 그림과 같습니다. 아직 이해가 가지 않아도 걱정하지 마세요.
스코프 체인은 기본적으로 "참조 체인"입니다. 이 참조 체인은 실행 컨텍스트에서 참조할 수 있는 값(및 다른 스코프)에 대한 참조를 포함하는 객체에 대한 참조를 포함합니다. (⛓ : 헤이, 이 컨텍스트 내에서 참조할 수 있는 값들은 이게 전부야 ). 스코프 체인은 실행 컨텍스트를 만들 때 생성됩니다. 즉 런타임에 생성됩니다.
하지만, 이 게시물에서는 activation object나 실행 컨텍스트에 대한 언급은 하지 않겠습니다. 스코프에만 집중합시다! 다음 예시에서 실행 컨텍스트 내부의 키/값 쌍은 스코프 체인이 그 변수에 대해 가지는 참조를 나타냅니다.
글로벌 컨텍스트의 스코프 체인은 3개의 변수에 대한 참조를 가지고 있습니다 : name
은 Lydia
, age
는 21
, city
는 San Francisco
.
로컬 컨텍스트에서는 2개의 변수에 대한 참조를 가지고 있습니다. name
은 Sarah
, age
는 22
getPersonInfo
함수에서 변수에 접근할 때, 엔진은 먼저 로컬 컨텍스트를 확인합니다.
로컬 스코프 체인은 name
, age
에 대한 참조를 가지고 있습니다! name
은 Sarah
, age
는 22
라는 값을 가지고 있습니다. 하지만, city
에 접근할 때 무슨 일이 일어날까요??
city
에 대한 값을 찾기 위해서 엔진은 현재 스코프 체인에서 내려갑니다. 이것은 엔진이 쉽게 포기하지 않는 다는 것을 의미합니다. 엔진은 city
의 값을 지역 스코프가 참조하는 외부 스코프, 이 경우에는 글로벌 스코프에서 찾을 수 있는지 열심히 일합니다.
글로벌 실행 컨텍스트에서 우리는 city
를 San Francisco
로 선언했습니다. 따라서 city
에 대한 참조를 가지고 있습니다. 이제 우리는 해당 변수의 값을 가지고 있고, getPersonInfo
함수는 Sarah is 22 and lives in San Francisco
를 반환할 수 있습니다. 🎉
우리는 스코프 체인에서 내려갈 수 있지만, 올라갈 수는 없습니다. 몇몇 사람들은 내려가다, 올라가다를 반대로 말 하기도하니 정확히 말하면 "외부 스코프로는 갈 수 있지만, 내부 스코프로는 갈 수 없습니다". 나는 이것을 폭포의 일종으로 시각화하고 싶습니다.
또는 더 깊이
이 예시 코드를 한 번 보세요
거의 비슷하지만, 한 가지 큰 차이점이 있습니다. 우리는 city
를 글로벌 스코프가 아닌getPersonInfo
에 선언했습니다. getPersonInfo
함수를 호출하지 않았으니 로컬 컨텍스트가 생성되지도 않았습니다. 하지만 우리는 글로벌 컨텍스트에서 name
, age
, city
에 접근하려고 합니다.
이것은 ReferenceError
를 일으킵니다! 글로벌 스코프에서는 city
변수의 참조를 찾을 수 없고, 살펴볼 외부 스코프도 없으며, 스코프 체인을 올라갈 수도 없습니다.
이 방법으로 스코프를 이용해 변수를 "보호"하고, 변수명을 재사용할 수 있습니다.
전역, 로컬 스코프 외에도 block scope도 있습니다. let, const로 선언된 변수는 가장 가까운 대괄호로 범위가 지정됩니다 { }
위 코드의 스코프를 시각화하면 아래와 같습니다.
글로벌, 함수, 그리고 두 개의 블록 스코프가 있습니다. 변수들이 대괄호로 범위가 지정되었기 때문에 우리는 message
를 두 번 선언할 수 있습니다.
빠르게 요약하자면