JavaScript Visualized: ⚡️⛓ Scope (Chain)
Posted on September 02, 2020 - 4 min readreference: 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
의 값을 알고 있는 걸까요?
우선, 메모리 공간은 각각 다른 컨텍스트에 할당됩니다. 기본적인 전역 컨텍스트(브라우저 내에서 window
입니다. Node에서는 global
구요.)가 있고, 호출된 getPersonInfo
함수를 위한 지역 컨텍스트가 있습니다. 각 컨텍스트는 스코프 체인을 가집니다.
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
라는 변수에 대한 참조를 찾을 수 없고 찾아갈 외부 스코프도 없으며, 스코프 체인을 올라갈 수가 없으니까요.
이런 식으로 여러분들의 변수를 “보호”하고 변수명을 재사용하기 위해 스코프를 사용할 수도 있습니다.
Besides global and local scopes, there is also a block scope. Variables declared with the let
or const
keyword are scoped to the nearest curly brackets ({}
).
글로벌과 지역 스코프 외에도, 블럭 스코프라는 것도 있습니다. let
과 const
키워드로 선언된 변수들은 가장 가까운 중괄호({ }
)에 대한 스코프를 갖습니다.
const age = 21
function checkAge() {
if (age < 21) {
const message = "You cannot drink!"
return message
} else {
const message = "You can drink!"
return message
}
}
스코프를 다음과 같이 시각화할 수 있습니다:
전역 스코프, 함수 스코프와 두 개의 블럭 스코프가 있습니다. message
변수는 중괄호에 대한 스코프를 가지기 때문에 두 번 선언할 수 있습니다.
정리해 보겠습니다:
- 스코프 체인은 현재 컨텍스트 내에서 접근할 수 있는 값들의 참조에 대한 체인입니다.
- 스코프를 사용하여 스코프 체인에 추가로 정의된 변수명을 재사용 할 수 있습니다. 스코프 체인은 올라갈 수 없고 내려가는 것만 가능하기 때문입니다.
이것들이 스코프 (체인)에 대한 내용입니다! 사실 할 말이 더 많이 있어서 시간이 되면 추가 정보를 넣을 수도 있을 것 같아요. 어려운 점이 있으시면 자유롭게 질문해 주세요! 💕