개발 기술/개발 이야기

랙시컬 스코프(정적 스코프)는 무엇일까?

by GicoMomg 2021. 11. 22.

랙시컬 스코프가 무엇인지 알기에 앞서,
스코프 그리고 스코피 체인을 알아본 후 렉시컬 스코프에 대해 알아보자

1. 스코프(Scope)?

  • 스코프는 말 그대로 범위를 뜻하며, 변수에 접근 가능한 범위를 말한다.
  • 스코프는 해당 변수가 어디서(where) 선언되었는지에 따라 결정되며, 크게 전역, 지역 스코프로 나뉜다.
  • 전역스코프는 블록 바깥({}) 영역을 의미하여, 블록 바깥에 선언된 변수를 전역변수라고 부른다.
  • 전역변수는 어떤 함수, 블록에서든 호출할 수 있다.
const variable = 1;  // 전역변수

function print() {
  console.log(variable);  // 1
}
console.log(variable);    // 1

  • 이와 달리 지역스코프는 블록({}), 함수 내부 영역을 뜻하여, 지역스코프에 선언된 변수는 지역변수이다.
  • 전역변수와 달리 어디에서든 호출할 수 없으며 함수, 블록 내에서만 접근할 수 있다.
function print() {
  const test = 12;
  console.log(test)   // 12
}

console.log(test)     // test is undefined

  • 이러한 지역변수는 변수 선언 방식에 따라 스코프가 나뉘는데,
  • var로 선언한 경우 함수 스코프, let & const로 선언한 경우 블록 스코프가 된다.
  • 그렇다면, 함수, 블록 스코프는 무엇일까?

2. 함수 스코프, 블록 스코프

(1) 함수 스코프

  • 함수 몸체에 선언된 변수는 해당 함수에서만 유효하며, 이 유효범위를 함수 스코프라고 부른다.
  • var로 선언된 변수는 모두 함수 스코프를 따른다.
  • 아래 코드에서 함수 내부에서 var로 변수를 선언한 모습이다.
function test() {
  var variable = 'world';
}
console.log(variable) // hello is not defined
  • variable을 함수 test()에 선언되었으며, variable는 함수스코프에 있다.
  • 그렇기 때문에 함수 바깥에서 variable를 호출하면 undefined 에러가 발생한다.

  • 만약 블록에서 var로 변수를 선언하면 어떻게 될까?
  • 앞서 언급했듯이 var은 함수 스코프를 따르므로, 블록과 상관없이 호출가능하다.
{
  var variable = 'world';
}
console.log(variable)      // world

(2) 블록 스코프

  • 블록 몸체에 선언된 변수는 해당 블록에서만 유효하며, 이 유효범위를 블록 스코프라고 부른다.
  • let, const로 선언한 변수는 블록 스코프를 따른다.
  • 아래 코드에서 블록 내부에서 const로 변수를 선언한 모습이다.
{
  const variable = 'world';
  console.log(variable)     // world
}
  • variable은 블록 내부에서 선언되었으며, 블록 내부에서는 해당 변수에 접근할 수 있다.

{
  const variable = 'world';
}
console.log(hello)  // hello is not defined
  • 하지만 블록 바깥에서 variable에 접근하려고 하면, undefined 에러가 발생한다.
  • 그 이유는 variable는 블록 스코프에 속하는 변수이기 때문이다.

function test() { // block
  const hello = 'world';  
}
console.log(hello)  // world
  • 만약 함수 내부에서 const로 변수를 선언하면 어떻게 될까?
  • const는 블록스코프를 따르기 때문에 함수 내부에서 선언해도 바깥에서 호출할 수 있다!

3. 스코프 체인?

  • js 스코프에 특징이 있는데 그건 바로 스코프 체인이다.
  • 스코프 체인이란, 현재 스코프에 해당 변수가 없다면 상위 스코프에서 찾는 걸 말한다.
  • print()에서 variable을 출력하고자 한다.
const variable = 'world';
function print(){
  console.log(variable);
}

  • 하지만 print() 내부에는 해당 변수가 없다!
  • 이 경우 스코프 체인으로 인해 상위 스코프를 탐색하게 된다.
  • print()의 상위스코프에 variable이 존재하므로 이 변수를 사용하게 된다.
const variable = 1;
function print(){
  console.log(variable);
}

print(); // world

4) 랙시컬 스코프?

  • 랙시컬 스코프는 함수가 어디에 선언되어 있느냐에 따라 결정된다.
  • 다른 말로 정적 스코프라고 부르며, js에서 함수는 정적 스코프를 따른다.
  • 함수가 중첩되어 있을 시, 내부 함수에 호출 대상이 없다면 상위스코프에서 찾는다. (스코프 체인 특성)

🤔 그렇다면 상위 스코프의 기준은 무엇일까?

  • 상위스코프는 함수가 어디에 선언되어있는지에 따라 결정된다.
  • 만약 A함수 내부에서 B함수가 선언되어 있다면, B함수의 상위스코프는 A함수이다.
function A(){             // A는 B의 상위 스코프임
  var variable = 'world';
  function B(){           // B는 A에 선언되어 있음
    console.log(variable);
  }
  B();
}
A(); // world

🤔 만약 아래와 같은 경우에는 결과는 어떻게 될까?

var variable = 'world';
function A(){     
  var variable = 'test';       
  B();
}
function B(){     
  console.log(variable);
}
A();
  • 답은 바로 world이다.
  • 이유는 차근차근 살펴보자.

var variable = 'world'; 
  • world를 값으로 가지는 variable는 전역변수이다.

function A(){     
  var variable = 'test';       
  B();
}
  • 그리고 A()내부에는 variable변수가 선언되어 있으며 B()를 호출한다.

function B(){     
  console.log(variable);
}
  • B()는 variable을 출력하는 함수로 전역레벨에 선언되어 있다.
  • 그리고 선언된 B()의 가장 가까운 상위스코프는 전역 변수 variable이다.

  • 앞서 언급했듯이 함수는 랙시컬 스코프를 따르며, 선언된 위치를 기준으로 상위 스코프를 찾는다.
  • 그렇기 때문에 variable 출력 결과가 전역 변수 variable가 나오는 것이다.
var variable = 'world';
function A(){     
  var variable = 'test';       
  B();
}
function B(){     
  console.log(variable);
}
A();      // world

반응형

댓글