(https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd) 글을 번역했습니다.
스코프 체인을 위한 시간이다 🕺🏼 이 포스트는 기본적으로 실행 컨택스트의 기본을 알고있다고 가정한다. 그러나 곧 실행 컨텍스트에 대해서 포스트를 쓸 것이다. 😃
다음의 코드를 보자.
const name = "Lydia"
const age = 21
const city = "San Francisco"
function getPersonInfo() {
const name = "Sarah"
const age = 22
return `${name} is ${age} and lives in ${city}`
}
console.log(getPersonInfo())
우리는 getPersonInfo
함수를 호출했다. 그리고 name
과 age
, city
변수들의 값들을 포함하는 문자열(Sarah is 22 and lives in San Francisco
)을 반환한다. 하지만 getPersonInfo
함수는 city
변수를 갖고 있지 않는다🤨? 어떻게 city
값을 알고 있을까?
우선, 메모리 공간이 다른 컨텍스트들을 위해 설정(set up)되었다. 우리는 두 가지 컨택스트를 가지고 있다. 기본 글로벌 컨택스트(global context)(브러우저에선 window
, Node에선 global
), 그리고 호출되는 getPersonInfo
함수를 위한 로컬 컨택스트(local context)이다. 각 컨택스트는 역시 각각의 스코프 체인이 있다.
getPersonInfo
함수를 위해서, 스코프체인은 이와 같이 보인다.(걱정마라, 아직은 이해가 안가도 된다.)
스코프체인은 기본적으로 오브젝트들(objects)에 대한 "참조의 체인(chain of references)"이다. 객체들은 실행 컨택스트(execution context)안에서 참조할 수 있는 값들(또는 다른 스코프)에 대한 참조를 포함한다. (⛓: "이봐, 여기엔 모두있어구. 이 컨텍스트 안에서 참조할 수 있는 것들 말이야.") 실행 컨텍스트가 생성 될때 스코프 체인이 생성된다, 즉 실행(runtime)중에 생성된다!
그렇지만, 이 포스트에서는 활성 객체(activation object)나 실행 컨택스트를 이야기하고 싶지않다. 스코프에만 집중하자!. 다음 예제에선, 실행 컨택스트에서 키/값 쌍이 참조들로 나타난다. 이 참조들은 스코프체인이 갖는 변수들이다.
전역 실행 컨텍스트(global execution context)는 3가지 변수들에 대한 참조를 가지고 있다. Lydia
값을 가지고 있는 name
, 21
값을 가지고 있는 age
, San francisco
값을 가지고 있는 city
.
지역 콘텍스트(local context)에서는, 2가지 변수들에 대한 참조를 가지고 있다. Sarah
값을 가지고 있는 name
, 22
값을 가지고 있는 age
.
우리가 getPersonInfo
함수 안에 있는 변수들에 접근할 때, 엔진은 처음으로 지역 스코프 체인을 검사한다.
지역 스코프 체인은 name
과 age
에 대한 참조를 가지고 있다! name
은 Sarah
란 값을 가지고 있고, age
는 22
의 값을 가지고 있다. 하지만 city
에 접근하려고 할 때 무슨일이 벌어날까?
city
의 값을 찾기위해서, 엔진은 "스코프 체인을 따라 내려간다". 이건 기본적으로 엔진이 쉽게 포기하지 않는다는 것을 의미한다. 지역 스코프가 참조하는 밖의 스코프(outer scope)(이 경우에선 전역 객체(global object))안의 변수 city
에 대한 값을 찾기 위해 열심히 노력한다.
전역 컨텍스트에선, San Francisco
를 가지고 있는 변수 city
는 선언되었다, 그래서 city
변수에 대한 참조를 가지고 있다.
지금 변수들에 대한 값을 가지고 있다, 함수 getPersonInfo
는 문자열 Sarah is 22 and lives in San Francisco
를 반환한다.🎉
우리는 스코프 체인을 따라 내려갈(go down) 수 있지만, 스코프체인을 올라갈(go up) 수는 없다.(맞다, 이건 아마 혼란스러울 것이다. 왜냐하면 몇몇 사람들은 올라간다는 말대신 내려간다고 하기도 한다, 그래서 다시 말하자면, 밖의 스코프(outer scopes)로 갈 수 있다고 한다. 하지만 안으로(inner)는 갈 수 없다....(안으로(inner)...?). 나는 이것이 일종의 폭포 같이 시각화하고 싶다.
또는 깊어진다.
이제 코드로 예제를 보자.
이건 거의 똑같지만, 큰 차이점 하나가 있다. 오직 getPersonInfo
안에서 city
는 선언된다. 그리고 전역스코프에는 선언되지 않는다. 우리는 getPersonInfo
함수를 호출하지 않는다. 그래서 지역 컨택스트 또한 생성되지 않는다. 그러나, 글로벌 컨택스트에서 name
,age
,city
에 접근하려고 한다.
ReferenceError
를 뱉는다! 글로벌 컨택스트에선 city
라고 불리는 변수에 대한 참조를 찾을 수 없다, 그리고 찾을 수 있는 밖의 스코프도 없고, 스코프 체인을 올라갈 수 없다.
이런식으로, 변수들을 "보호"하고 변수명을 재사용하는 방법으로 스코프를 사용할 수 있습니다.
또한 전역과 지역 스코프말고, 블록 스코프(block scope)라고 있습니다. let
이나 const
키워드로 선언되는 변수들은 가장 가까운 중괄호({})로 범위(scoped)지어진다.
const age = 21
function checkAge() {
if (age < 21) {
const message = "You cannot drink!"
return message
} else {
const message = "You can drink!"
return message
}
}
스코프를 시각화할 수 있다.
코드에선 전역 스코프, 함수 스코프, 두 가지 블록 스코프를 가진다. 변수 message
는 두 번 선언되어 진다, 변수들이 중괄호 스코프로 범위지어기지 때문이다.
빠르게 되돌아보자.
스코프(체인)이었다!. 이것에 대해서 더 많은 이야기 할 수 있으므로 편한 시간에 정보를 추가할 수 있다. 무엇이든 어려움을 겪고 있으면 편하게 물어보라, 나는 돕는 것을 좋아한다!💕