CS/프로그래밍

스코프, 스코프 체인

고래강이 2024. 1. 2. 09:19

개요

  • 스코프
  • 스코프 체인

스코프

식별자의 유효범위로 변수에 접근할 수 있는 범위를 말하며 참조 대상 식별자를 찾아내기 위한 규칙이다.

 

var x = "global";

function foo() {
  var x = "function scope";
  console.log(x);
}

foo(); // function scope
console.log(x); // global

위와 같은 코드에서 전역변수인 x는 어디서든 참조할 수 있지만 foo() 내부에 선언된 지역변수 x는 foo() 내부에서만 참조할 수 있다. 이러한 규칙을 스코프라고 한다.

 

스코프가 필요한 이유)

  • 의도치 않은 변수 값의 변조를 방지 (변수명의 충돌)
  • 효율적인 메모리 관리 (코드 블럭 안의 참조값들은 코드가 실행될 때만 메모리에 할당 됨)

전역변수와 지역변수)

let global = 30;

function scope() {
  let local = 21;
  console.log(global);
};

scope(); // 30
console.log(local); // Uncaught ReferenceError: local is not defined
  • 스코프라는 함수의 내부에선 변수 global의 값을 참조할 수 있다. 모든 코드 블럭에서 접근 가능한 변수를 전역변수라고 하며 이러한 전역 변수가 선언되는 스코프를 전역 스코프라고 한다.
  • 코드 블럭 안에서 선언되어 외부에서 접근할 수 없는 변수를 지역변수라고 하며 이러한 지역변수는 지역 스코프에 선언되며 외부에서 변수 local에 접근한다면 참조오류가 발생한다.

함수 레벨 스코프)

함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다.
자바스크립트는 기본적으로 함수 레벨 스코프를 따른다.  
  • 처음 예시를 통해서 함수 레벨 스코프를 알 수 있다.
  • 동일한 변수명을 가진 변수가 각각 지역 스코프와 전역 스코프에 선언되었고 이를 참조했을 시에 지역변수를 우선하여 참조한다.
var x = "global";

function foo() {
  var x = "local";
  console.log(x);
}

foo(); // local
console.log(x); // global

이는 실행 컨텍스트의 스코프 체인에 의해 참조 순위에서 전역변수가 뒤로 밀렸기 때문이다.

그로 인해 함수 내부에서 전역변수를 참조하여 전역변수의 값을 변경할 수 있기 때문에 예기치 못한 에러가 발생할 수 있다. 이러한 개념은 전역변수 뿐만아니라 상위 함수에 대해서도 적용이 된다.

블록 레벨 스코프)

코드 블록 내에서 유효한 스코프를 의미한다.
ES6에서 등장한 let, const로 선언된 변수는 블록 레벨 스코프를 지원한다.

 

  • 함수 레벨 스코프와 헷갈리는 부분이 있지만 좀 더 좁은 개념으로 받아들이면 된다
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

위 예시를 통해 함수 레벨과 블록 레벨의 차이점을 알 수 있다.

스코프는 필요한 여역에 한정하여 유효범위가 좁을수록 좋다고 생각되며 var보다 let, const가 많이 사용되는 이유 중 하나로 생각이 된다.

 

비 블록 레벨 스코프)

if (true) {
  var x = 5;
}
console.log(x); // 5

위 예시에서 x는 함수 내에서 선언된 것이 아니다 그렇기에 기본적으로 함수레벨의 스코프를 가진 자바스크립트에서는 전역스코프에서 선언된 전역변수로 취급된다.

 

렉시컬 스코프)

var x = 1;

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

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

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

위 예제의 결과를 예측하면서 렉시컬 스코프를 알아보자

위 실행결과는 bar()의 상위스코프가 무엇인지를 알 수 있는 코드로 프로그램에서 상위 스코프를 결정하는 방식은 2가지가 있다.

  • 동적 스코프 : 함수를 어디서 호출하였는지에 따라 상위 스코프가 결정된다.
  • 렉시컬 스코프 (정적 스코프) : 함수를 어디서 선언했는지에 따라 상위 스코프를 결정한다. 자바스크립트를 포함한 대부분의 언어는 렉시컬 스코프를 따른다.

그렇기에 bar()는 전역 변수 1을 출력한다

 

암묵적 전역)

선언하지 않은 식별자에 값을 할당하였을 경우 전역 객체의 프로퍼티가 되는 것으로 변수가 아니라 프로퍼티로써 참조되는 것
var x = 10; // 전역 변수

function foo() {
  y = 20; // 선언하지 않은 변수
  console.log(x + y);
}

foo(); // 30

위 예시와 같이 선언하지 않은 변수인 y는 참조에러가 발생해야하지만 자바스크립트 엔진은 이를 window.y = 20으로 해석하여 프로퍼티를 동적으로 생성한다. 이는 마치 전역 변수처럼 작동하지만 변수는 아니므로 변수 호이스팅이 발생하지 않고 delete를 통한 삭제도 가능하다

 


스코프 체인

일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례로 저장하고, 의미 그대로 각각의 스코프가 어떻게 연결되고 있는지를 보여주는 것
  • 실행컨텍스트를 통해서 스코프 체인의 작동 방식을 알 수 있다.

스코프 체인 작동 방식)

  1. 애플리케이션이 실행 후 종료될 때까지 유일한 전역 실행 컨텍스트가 존재하며 LIFO구조의 스택으로 실행컨텍스트가 실행이 된다.
  2. 함수 호출순으로 스택이 쌓이게 되고 안에서부터 탐색을 시작한다.
  3. 자신이 속해 있는 스코프의 변수들을 참조할 수 있으며 해당 코드 레벨에 참조값이 없다면 상위 레벨의 스코프로 참조 값을 찾아 나아간다.
  4. 전역 스코프에도 참조값이 없다면 에러를 반환한다(엄격모드에서)

 

 

 

참고자료 : 블로그1 , 블로그2 , 블로그3 , 모던자바스크립트

'CS > 프로그래밍' 카테고리의 다른 글

화살표 함수와 일반 함수  (0) 2024.01.08
리액트 Hook  (1) 2024.01.02
Context API  (1) 2024.01.01
JS, 이벤트 바인딩(Event Binding)  (0) 2023.12.26
props/state  (0) 2023.12.24