본문 바로가기

JavaScript

[JavaScript] JavaScript에서의 스코프

Scope는 모든 프로그래밍 언어에서 기본이 되는 아주 중요한 개념이다. JavaScript에서는 다양한 스코프 개념이 있고 다른 언어와 차별되는 스코프 특징이 있기 때문에 주의가 필요하다.

 

 

function add(x, y) {
  console.log(x, y); // 1
  return x + y;
};

add(5, 5);

console.log(x, y); // 2

 

위의 코드를 보면 어떤 결과가 예상되는가? 1번의 경우에는 5, 5가 나오겠지만 2번의 경우에는 참조 에러가 발생한다. 함수의 매개변수의 경우에는 함수 몸체 내부에서만 참조가 가능하다. 그렇기 때문에 함수 블록 바깥에서 매개변수를 참조하게 되면 참조 에러가 발생한다.

 

 

변수의 경우

 

변수는 자신이 선언된 위치에 의해서 스코프가 결정된다. 사실 모든 식별자가 그러하다. 정리하자면 스코프는 식별자가 유효한 범위를 뜻한다.

 

https://velog.io/@denmark-choco/javascript-Scope

 

위 그림에서 볼 수 있듯이 변수가 어디에 선언되었는 가에 따라서 스코프가 결정된다. 또한 전역 스코프를 가진 변수의 이름과 함수 블록 내에 있는 변수의 이름이 같다면 코드 실행 시 context를 따라서 무엇을 참조할 지를 결정하게 된다. 이를 렉시컬 환경이라 부르며 이를 구체적으로 구현한 것이 실행 컨텍스트이다.

 

 

 

스코프의 종류

 

스코프에는 크게 전역 스코프와 지역 스코프가 있다. 예를 들어 전역 변수의 경우에는 전역 스코프를 가질 것이고 함수 몸체 내부의 경우에는 지역 스코프를 가질 것이다. 위 이미지에 선언된 변수를 살펴보면 변수c와 변수b는 각각 함수 second와 first의 내부에 있으므로 지역 스코프를 가진다. 반면 변수 a의 경우에는 전역 스코프를 갖게 된다.

 

 

 

스코프 체인

 

JavaScript에서 함수는 전역에 있을 수도 있고 함수 내부에 중첩되어 존재할 수도 있다. 함수가 중첩 구조를 가지게 될 경우 스코프 또한 중첩되어 계층적으로 이루어질 수 있다. 위 이미지의 경우 second 함수가 first 함수 안에 존재하기 때문에 중첩 스코프를 이루고 first 함수로 인해 만들어진 스코프는 second 함수의 상위 스코프이다. 이러한 계층적 구조를 우리는 스코프 체인이라고 부른다.

 

https://www.stevethedev.com/blog/programming/javascript-scope-primer

 

변수를 참조할 때에 자바스크립트 엔진은 스코프 체인을 통해서 변수를 참조하는 코드의 스코프부터 상위 스코프로 이동하면서 선언된 변수를 찾는다. 자바스크립트 엔진은 이러한 스코프 체인을 기반으로 렉시컬 환경을 생성하고 식별자가 렉시컬 환경에 key로 등록되고 변수가 할당 되면 해당하는 값을 변경한다. 

 

 

Function Level Scope

 

지역 스코프는 함수 몸체 내부를 뜻하는 데 이는 함수에 의해서만 지역 스코프가 생성된다는 의미이다. 코드 블록을 사용하는 조건문이나 반복문도 지역 스코프를 생성한다. 이러한 특성을 Block level scope라고 한다. 특수한 경우가 있는데 es5에서 사용하는 var 키워드의 경우 오로지 함수의 코드 블록만 지역 스코프로 인정한다. 

 

var test = 1;

if (true) {
  var test = 10;
};

console.log(test);

 

 

var 키워드는 함수의 코드 블록만 지역 변수로 인정하기 때문에 코드 블럭 안에서 선언되었다 하더라도 모두 전역 변수로 취급한다. 위에 코드의 결과는 10이 나온다. 즉 함수를 제외한 코드 블럭에서는 전역 변수가 재할당이 된다는 의미이다.

 

 

 

렉시컬 스코프

 

JavaScript는 렉시컬 스코프를 따르므로 함수를 어디서 정의했는가에 따라서 상위 스코프를 결정한다. 함수가 호출된 위치는 상위 스코프 결정에 아무런 영향도 주지 않는다. 이는 클로저를 설명할 때 더 자세히 다뤄보도록 하겠다.