Pie_Archive

[Java Script] 13. 스코프 본문

카테고리 없음

[Java Script] 13. 스코프

코딩파이 2022. 8. 25. 21:45

** 본 글은 모던 자바스크립트 DEEP DIVE 를 읽고 정리한 글입니다.
** 본인이 책 내용의 이해를 돕기 위해 정리한 글이며, 부정확한 정보전달이 있을 수 있습니다. 
** 피드백은 언제나 환영입니다!


1. 스코프 (scope) ?

스코프(scope) 모든 식별자가 참조하는 유효 범위이다.

 

다음 예제를 통해 스코프(scope) 가 어떻게 결정되는지 보자

var x = "전역x";

function 전역함수 () {
	var x = "내부x";
	console.log(x); // 내부x, 내부x 를 참조하여 출력합니다.
}
전역함수();

console.log(x) // 전역x, 전역x를 참조하여 출력합니다.

// 두 변수 x는 다른 메모리를 가집니다. 다른 변수에요.

똑같은 식별자를 가진 변수 x특정함수 내부전역에서 출력한 결과, 다른 결과가 나온다.

이는 console.log(x) 에서 어떤 x를 참조하느냐에 따라 다른 결과가 나온 것이다.

위 예제에서는 함수 블록문을 기준으로 다른 x를 참조하였으며

이렇게 참조하는 유효범위에 대한 내용이 스코프(scope) 라 할 수 있다.

 

코드의 문맥(Context)과 환경(environment)

실행할 코드의 주변에 어떤 변수등 참조할 코드가 있는지와 같은 환경
렉시컬 환경(lexical environment) 이라고 부른다.
렉시컬 환경을 참조하여 코드를 실행하는 것실행 컨택스트(execution context) 라고 부른다.
어려운 개념이니 추후에 자세히 알아보자.

 

2. 스코프의 종류

딱 두가지만 기억하자.

전역(global) / 지역(local)

1. 전역 스코프 (Global Scope)

어떠한 함수 안에서 선언된게 아니기 때문에 어디서든 참조할 수 있다.

다만, 지역 스코프 (Local Scope) 에서 변수가 재할당 되면 값이 변할 수 있음을 유의하자.

var x = "전역x"; // 전역변수

function 전역함수 () {} // 전역함수

 

2. 지역 스코프 (Local Scope)

특정 함수(문) 안의 범위를 가리키며, 특정 문 안에서 선언된 변수나 함수를 지역변수 / 지역함수 라고 부른다.

특히, 본인과 상위 (부모) 스코프를 참조 할 수 있지만,

본인의 하위(자녀) 스코프는 참조할 수 없는 점을 꼭 기억하자.

이 스코프의 참조 관계를 스코프 체인 (Scope Chain) 이라고 한다

var 전역변수 = "전역변수";
function 전역함수 () {
	var 지역변수 = "지역변수";
	console.log(지역변수); // 같은 함수 안의 지역스코프 참조 가능
    console.log(전역변수); // 외부의 전역 스코프 참조 가능
}
전역함수();

// 함수에서의 스코프 참조
function 일반함수() {
  console.log("일반함수 입니다.");
}

function 중첩함수 () {
  function 일반함수() {
    console.log("중첩함수입니다.");
  }
  
  일반함수();
}

중첩함수(); // "중첩함수입니다" 가 출력된다.

 

3. 함수레벨 스코프

자바스크립트를 제외한 대부분의 언어는 코드블록을 기준으로 스코프가 생성된다.

그러나 자바스크립트는 오로지! 함수기준으로만 스코프가 생성됬었다.

ES6 이전까지 사용되었던 var오로지 함수를 기준으로만 스코프를 생성하며

ES6 이후 사용되는 let / const 는 다른 언어처럼 블록문을 기준으로 스코프가 생성된다.

 

var i = 10; // 근데 일반 변수명을 이런식으로 웬만하면 생성하지 말자.

for (var i = 0; i <5; i++) {
  console.log("함수내부", i)
}

console.log(i) // 10 이었던 i 가 5가 되었다. for문을 실행하면서 i가 변경되었기 때문이다.

위 코드에서 varlet 키워드로으로 변수 i 는 10 그대로 출력된다. 

 

 

4. 렉시컬 스코프

스코프를 결정하는 패턴은 크게 두가지가 있다.

  1. 동적 스코프
    함수를 호출하는 시점에서의 환경을 참조한다.
  2. 정적 스코프 (렉시컬 스코프 Lexical Scope)
    함수를 선언하는 시점
    에서의 환경을 참조한다.
    자바스크립트를 비롯한 대부분의 프로그래밍 언어는 렉시컬 스코프이다.

var x = 1;

function foo() {
  var x = 10;
  bar(); // 여기서 실행하면 x = 10을 참조할 것 같지만
}

function bar() {
  console.log(x); // bar 함수의 선언 시점에서 x는 전역변수 x = 1을 참조한다. 
}

foo(); // 1
bar(); // 1

위 예제처럼 분명히 foo 함수 지역 스코프 안에서 bar 를 호출했지만

var x = 10 참조가 아닌 전역으로 선언된 var x = 1 을 참조했다.

이렇듯 자바스크립트는 항상 함수를 호출이 아닌 선언시의 스코프와 환경을 참조함을 기억하자.

 


오늘의 후기

스코프 역시 실제 코딩을 하면서 자연스럽게 접하게 되는 개념인지라 이미 많은 부분 알고 있었지만,

렉시컬 스코프같은 개념에 대해서는 처음 알았다.

그래서 당연히  "x는 10이지!" 를 자신감 있게 외치면서 확인해봤으나, 1이 나온걸 보고 적잖이 당황했다.

이런 사소한 부분 때문에, 디버깅을 성공하고도 버그의 원인을 잘 알지 못했던 일이 생겼을 거라고 생각한다.

오늘도 사소한 부분이 채워져서 만족스럽다.