본문 바로가기

웹/JavaScript

[JavaScript] 스코프(scope)

 

스코프란

현재 실행되는 컨텍스트를 뜻한다. 자바스크립트의 변수나 함수는 선언 될 때 그 위치에 따라 스코프를 가지며, 참조하는 대상을 찾기 위한 규칙이다. 

 

예를 들어보자. 서로 다른 범위에 이름이 동일한 2개의 변수 x가 선언되어있을 때, x의 값을 콘솔에 출력하려고 한다. 이 때 현재 맥락에서 두 개의 x 중 어느 쪽을 참조하는지 알기 위해 필요한게 스코프라고 할 수 있다. 

var x = 'global';

function localFunction(){
    var x = 'local';
    console.log(x); //지역 스코프. local이 출력됨
}

localFunction();
console.log(x); //전역 스코프. global이 출력됨

 

전역 스코프와 지역 스코프

자바스크립트는 함수 레벨 스코프를 따른다. 함수 블록 내에서 선언된 변수는 해당 함수 코드 블록 안에서만 유효하다. 이런 이유로 스코프는 크게 두 가지로 나눌 수 있는데, 전역 스코프(global scope)와 지역 스코프(local scope)이다. 

 

- 전역 스코프: 전체 범위, 즉 어디에서나 참조할 수 있다. 전역 객체인 window의 프로퍼티가 된다. 위의 예시코드에서 함수 바깥에 선언된 'global'의 x가 전역 스코프를 가진다. 

- 지역 스코프: 함수 코드 블록 내에 선언된 경우 지역 스코프가 되며, 해당 함수와 그 하위 범위에서만 참조할 수 있다. 위의 예시코드에서 함수 localFunction() 내부에 선언된 'local'의 x가 지역 스코프를 가진다. 이 x는 localFunction() 바깥에서는 유효하지 않는 변수가 된다. 

 

전역 스코프를 가지는 변수를 전역 변수, 지역 스코프를 가지는 변수를 지역 변수라고 한다. 

 

스코프 체인

함수 내부의 변수는 자기 스코프에서 가장 가까운 곳의 변수를 참조한다. 이 때, [내부 함수 -> 외부 함수의 변수 접근] 은 가능, but [외부 함수 -> 내부 함수로의 변수 접근]은 불가능.

해당 규칙에 따라 아래의 코드에서 맨 마지막 라인에서 console.log(z)에서 찾는 변수 z는 내부 함수 f2에 선언되어 있기 때문에 외부의 전역 범위에서 찾으면 없는 것이 되어 undefined가 콘솔에 출력된다.

var x = 'global';

function f1(){
  var y = 'local outer';
  function f2(){
    var z = 'local inner';
    console.log(x, y, z); // global, local outer, local inner
  }
}

console.log(z); //undefined

위의 코드를 보면 x를 콘솔 출력할 때, 먼저 x를 함수 자신인 f2의 스코프에서 찾고, 없으면 한단계 외부로 넘어가 f1 스코프에서, 거기에도 없으면 전역 스코프로 넘어가 찾는 과정을 거친다. 이렇게 하나씩 거슬러가며 찾는 것을 스코프 체이닝(scope chaining)이라고 하며, 거슬러 가기 위한 스코프의 연결리스트를 스코프 체인(scope chain)이라고 한다.

 

렉시컬 스코프

함수의 선언 위치에 따라 상위 스코프를 결정하는 것을 말한다. 정적 스코프라고도 부른다. 자바스크립트는 렉시컬 스코프를 따른다. 

반대로 함수의 호출 위치에 따라 상위 스코프를 결정하는 것을 동적 스코프라고 한다. 

아래의 코드를 보자. 

var x = 'global';

function first() {
  var x = 'local';
  second();
}

function second() {
  console.log(x);
}

first(); // (1)
second(); // (2)

 

주석의 (1), (2)가 표시된 라인에서 어떤 값이 출력될까? 

 

1. 렉시컬 스코프로 결정하는 경우

 - (1): 선언된 3~6라인의 first()를 기준으로, x가 지역 스코프로 선언되어있다. 따라서 local이 출력될 것이다. 

 - (2): global이 출력될 것이다.

2. 동적 스코프로 결정하는 경우

 (1)과 (2) 모두 호출된 위치가 특정한 함수 내부가 아니다. 둘 다 global을 출력한다. 

 


참고 자료

MDN Docs https://developer.mozilla.org/ko/docs/Glossary/Scope

PoiemaWeb https://poiemaweb.com/js-scope

제로초 https://www.zerocho.com/category/Javascript/post/5740531574288ebc5f2ba97e