렉시컬 스코프

EenSung Kim·2021년 9월 28일
0

스코프란?

스코프(Scope) 란 유효 범위를 의미합니다. 변수를 (엄밀히 말하면 식별자를) 선언하는 위치에 따라 이 변수에 접근할 수 있는 범위가 형성되고, 이를 스코프라고 하는 것이죠.

일반적으로 반복문에서 사용하는 i 라는 변수나, 함수의 매개 변수 등을 생각해보면 조금 더 이해가 쉬울 것 같습니다. i 라는 변수는 반복문 내부에서만 사용이 가능하죠. 매개변수 역시 함수의 내부에서만 사용 가능합니다. 이처럼 변수는 선언되는 위치에 따른 스코프를 가집니다.

또한 스코프는 상하구조를 가지고 있습니다.

for(let i = 0; i < 5; i++) {
  for (let j = 0; j < 5; j++) {
    console.log(i);  // ?
  }
  console.log(j);  // ?
}

위 코드를 개발자 도구에서 실행해보면 반복 변수 i 가 0 으로 찍힌 다음, 반복변수 j 가 정의되지 않았다면서 Reference Error 를 띄울 겁니다. 내부의 반복문에서는 외부에서 정의된 i 변수에 접근이 가능하지만 외부의 반복문에서는 내부의 j 변수에 접근할 수 없기 때문입니다.


렉시컬 스코프란?

오늘의 주제는 렉시컬 스코프인 만큼 스코프에 대한 기본적인 이해를 짧게 건너뛰고 렉시컬 스코프가 무엇인지를 바로 알아보도록 하겠습니다. 렉시컬 스코프 (lexical scope) 란 다른 말로 정적 스코프 (static scope) 라고도 하며, 함수가 정의되는 시점에 상위 스코프가 결정되는 방식을 의미합니다.

let name = 'kim';

function hello() {
  let name = 'lee';
  world();
}

function world() {
  console.log(name);
}

hello();  // ?
world();  // 'kim'

전역 변수로 선언되고 초기화된 name 이라는 변수가 있습니다. hello 함수와 world 함수 또한 전역에서 정의되어 있죠. 그리고 world 함수는 hello 함수 안에서 호출되고 있습니다.

world 함수를 따로 호출했을 때는 'kim' 이라는 값을 출력합니다. 그렇다면 hello 함수는 어떨까요?

코드를 위에서 아래로 읽어내려가다보면 hello 함수의 내부에서 name 이라는 변수를 재선언하고 'lee' 로 초기화하고 있습니다. 스코프가 다르기 때문에 함수 내부에서 다시 name 이라는 변수를 선언하고 초기화할 수 있죠.

world 함수는 name 을 출력하게 되어있고 hello 함수 내부에서 name 이라는 변수는 'lee' 라는 값을 가집니다. 따라서 hello 함수 내부에서 호출한 world 함수는 'lee' 라는 값을 출력하지 않을까 생각하기 쉽죠. 하지만 실제로는 'lee' 가 아닌 'kim' 이라는 값을 출력합니다.

이것이 렉시컬 스코프의 예라고 할 수 있습니다. 함수의 상위 스코프가 함수가 정의되는 시점에 결정된 것이죠. 함수가 호출된 위치가 어디인지는 영향을 미치지 않습니다.

world 함수는 전역에서 정의되어 있습니다. world 함수의 내부에는 name 이라는 변수가 선언되어 있지 않으므로 자바스크립트는 전역 공간을 world 함수의 상위 스코프로 결정하게 되죠. 이미 상위 스코프가 이처럼 전역 공간으로 결정되어 있기 때문에, hello 함수에서 아무리 name 이라는 변수를 다시 선언한다 하더라도 이는 아무런 영향을 미치지 않습니다.

참고로 이러한 렉시컬 스코프는 클로저와 깊은 관계가 있다고 합니다. 클로저까지는 아직 한참 남은 터라 이 부분은 추후에 또 다루게 될 것 같습니다.


outro

렉시컬 스코프에 대해 짧게 다뤄봤습니다. 모든 내용은 모던 자바스크립트 Deep Dive 의 내용을 토대로 하고 있습니다. 수료 이후에 자바스크립트 기본기를 다지고 싶으시다면 꼭 한 번 읽어보시기를 권합니다. 오늘은 여기에서 마치도록 하겠습니다.

profile
iOS 개발자로 전직하기 위해 공부 중입니다.

0개의 댓글