프론트엔드/Javascript

자바스크립트 Scope 핵심정리

Jay_Jung 2024. 8. 15. 11:31

 

<참고 레퍼런스>

https://poiemaweb.com/js-scope

 

Scope | PoiemaWeb

스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙으로 자바스크립트는 이 규칙대로 식별자를 찾는다.

poiemaweb.com

 
 
이전에도 스코프 개념을 공부하긴 했었지만 몇개월 전부터 블로그를 작성하고 있는 나이기에 자바스크립트에서 중요한 개념인 Scope에 대해서 블로그로 기록해보고자 한다.
 
참고 레퍼런스는 모던 자바스크립 Deep Dive를 웹 사이트로 정리해놓은 poiemaweb 사이트이다.
 
 

<스코프란?>

개념: 스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 자바스크립트는 이 규칙대로 식별자를 찾는다.
 
대표적인 예시로 전역변수와 지역변수가 있으며 함수 내부에서 선언된 지역변수는 함수 내부에서만 참조할 수 있고 외부에서는 참조하지 못하는데 이러한 현상은 스코프라는 개념 때문에 발생한다.
 
구분은 밑에 첨부된 이미지처럼 다음과 같다.
지역 스코프는 함수 코드 블록이 형성한 스코프로 자신과 함수 내부에 있는 하위 함수에서 참조할 수 있다.
함수 밖에서 선언된 변수는 코드 블록 내에서 선언되었다할지라도 모두 전역 스코프을 갖게된다. 왜냐하면 자바스크립트는 함수 레벨 스코프(function-level scope)를 따르기 때문이다. -> 전역 스코프를 갖게되면 다른 쪽에서 참조 또한 가능하다. 

 

<스코프의 특징>

1. 자바스크립트는 기본적으로 함수 레벨 스코프(function-level scope)를 따른다. 함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(외부에서 참조할 수 없다)는 것이다.  ->  하지만 ECMAScript 6에서 도입된 let을 사용하면 블록 레벨 스코프를 사용할 수 있다.
✅ let y = 1 같은 경우 블록 레벨 스코프를 사용하고 있으며 전역변수로 초기화된 let y = 0과 구분되어 출력되는 것을 볼 수 있다. (블록 내부에 있기 때문에 외부에서 참조하지 못한다. 이런 경우는 C언어에서도 볼 수 있다.)

var x = 0;
{
  var x = 1;
  console.log(x); // 1
}
console.log(x);   // 1

let y = 0;
{
  let y = 1;
  console.log(y); // 1
}
console.log(y);   // 0

 
-> 해당 코드는 x가 전역 변수로 설정되어 있으므로 함수 내부에서 x를 참조할 수 있고 foo()를 호출하면 x는 100이고 console.log(x) 또한 함수 내부에서 x를 참조하여 값이 바뀌었기 때문에 100이 출력된다.

var x = 10;

function foo() {
  x = 100;
  console.log(x);
}
foo();
console.log(x);

 
 
2.  렉시컬 스코프
 
일단 코드를 먼저 봐보자. 답을 알기 전 어떻게 출력될 것인지 고민해보았지만 틀렸다..(10이 2번 출력될 것으로 예상)

var x = 1;

function foo() {
  var x = 10;
  bar();
}

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

foo(); // ?
bar(); // ?

 
 자바스크립트를 비롯한 대부분의 프로그래밍 언어는 렉시컬 스코프를 따른다. 렉시컬 스코프는 함수를 어디에 선언하였는지에 따라 상위 스코프가 결정되는 것을 말한다. 나 같은 경우 처음에 호출하는 걸 기준으로 생각했더니 답을 10 10으로 생각했었다. 자바스크립트는 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다. 
-> bar()함수의 선언부는 전역에 위치하므로 함수 bar의 상위 스코프는 전역 스코프이다. 즉, 위 예제는 전역 변수 x의 값 1을 두번 출력한다. 

-> foo() 내부에 있는 x는 foo()안에서만 유효한 지역 스코프/지역변수 이다. 이전 코드랑 비교해보면 이전 코드는 전역 스코프에 있는 전역 변수를 참조하여 10인 x를 100으로 변경한다.
 

VsCode에서 console로 찍어본 결과