스코프란 무엇일까요? MDN은 다음과 같이 설명합니다.
현재 실행되는 컨텍스트를 말한다. 여기서 컨텍스트는 값과 표현식이 “표현”되거나 참조 될 수 있음을 의미한다. 만약 변수 또는 다른 표현식이 “해당 스코프”내에 있지 않다면 사용할 수 없다. 스코프는 또한 계층적인 구조를 가지기 때문에 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가하다.
쉽게 말하자면 스코프는 변수에 접근할 수 있는 프로그램 상의 범위입니다. 자바스크립트 엔진은 스코프를 보고 변수의 접근 가능성을 결정합니다. 자바스크립트에는 3가지 종류의 스코프가 있습니다.
전역 스코프
전역 스코프는 전역 네임스페이스에 선언된 변수 또는 함수가 가지는 스코프입니다.
지역/함수 스코프
함수 또는 메소드 내에 선언된 변수 또는 함수가 가지는 스코프입니다. ES6 이전에 자바스크립트에서 변수를 선언하는 방법은 한가지, 바로 var
키워드를 사용하는 것이었습니다. var
를 사용하여 변수를 선언하는 자바스크립트는 다른 대부분의 프로그래밍 언어와 다른 동작 형태를 보입니다. 바로 변수가 함수 스코프를 가진다는 것이죠.
변수가 함수 스코프를 가지면:
- 함수 밖에서는 접근할 수 없습니다.
- 함수 외의 블록은 스코프로 취급되지 않습니다. 즉, 조건문과 반복문 등의 블록에서도 같은 함수 내에 있다면 접근 가능합니다.
if (true) {
var name = "Woody"
}
console.log(name) // 'Woody'
블록 스코프
ES6에서 추가된 let
과 const
는 var
와는 달리 블록 스코프를 갖습니다. 블록 스코프에서는 어떤 블록이라도 스코프가 됩니다. 함수, 조건문, 반복문 등 모든 블록이 스코프로 취급됩니다.
if (true) {
var name = "Woody"
}
console.log(name) // 'undefined'
여러분은 이제 자바스크립트에서 스코프가 어떤 의미를 갖는지 알게 되었습니다! 그렇다면 스코프 체인이란 무엇일까요?
스코프 체인
다시 한번 MDN의 스코프 문서를 읽어보면:
스코프는 또한 계층적인 구조를 가지기 때문에 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가하다.
이것이 스코프 체인입니다. 스코프 체인은 자바스크립트 코드에서 스코프가 어떻게 연결되어 있는지 정의합니다. 다음의 코드를 봅시다.
var x = "전역 x"
var z = "전역 z"
function 외부() {
var y = "외부 y"
console.log(x) // '전역 x'
console.log(y) // '외부 y'
function 내부() {
var x = "내부 x"
console.log(x) // '내부 x'
console.log(y) // '외부 y'
console.log(z) // '전역 z'
}
내부()
}
외부()
console.log(x) // '전역 x'
console.log(y) // 'Uncaught ReferenceError: y is not defined'
함수 내부에 함수가 중첩되어 있어 상당히 복잡해 보이네요. 자바스크립트 엔진은 복잡한 스코프 사이에서 스코프 체인을 탐색하며 변수의 값을 평가합니다.
내부
함수에서 x
, y
, z
의 값을 알기 위해서 자바스크립트 엔진은:
내부
함수 스코프에서x
,y
,z
의 값을 찾습니다. =>x = "내부 x"
외부
함수 스코프에서y
,z
의 값을 찾습니다. =>y = "외부 y"
- 전역 스코프에서
z
의 값을 찾습니다. =>z = "전역 z"
이처럼 변수는 존재하는 가장 가까운 상위 스코프의 값으로 평가됩니다. 만약 전역 스코프에서도 변수를 찾지 못하면 ReferenceError
를 throw합니다.