티스토리 뷰

Language/JavaScript

[Javascript] scope, scope chain

무화과(Fig) 2022. 7. 8. 13:55
var x = 'global';

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

foo(); // ?
console.log(x); // ?

위 예제는 이름이 같은 변수 x가 중복 선언되었습니다.  전역에서 변수 x를 참조할 때, 그리고 함수 foo 내부에서 변수 x를 참조할 때 이름이 중복된 2개의 변수 중 어떤 변수를 참조해야 할까요? 자바스크립트는 어떻게 변수를 식별하는 것일까요?

 

위 예제에서 전역에 선언된 변수 x는 어디에든 참조할 수 있습니다. 하지만 함수 foo 내에서 선언된 변수 x는 함수 foo 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없습니다. 이러한 규칙을 스코프라고 합니다.

 

 

 

 

 

 

1. 스코프(scope)란?


함수가 실행될때, 함수 내에서 변수에 대한 접근이 어떻게 되는지를 나타내는 용어입니다. (함수의 실행 컨텍스트 내에서의 변수 환경이 무엇인지) 스코프는 함수를 기반으로 한 용어입니다.

 

 

정리

스코프란 변수에 접근할 수 있는 범위를 말한다.

 

 

 

 

 

 

 

 

 

 

2. 컨텍스트(context)


this 키워드 값이 무엇인지를 나타내는 용어입니다. 현재 실행 컨텍스트 내에서 어떤 객체를 참조하고 있는지를 의미합니다. 컨텍스트는 객체를 기반으로 한 용어입니다.

 

 

 정리

  • 스코프 : 함수가 선언되면 무조건 스코프가 생성됩니다.
  • 컨텍스트: 함수가 속해있는 객체가 무엇인지 의미합니다. (만약 함수가 글로벌 스코프에서 선언되었다면, 이때의 컨텍스트는 global(window)입니다.)

 

 

 

 

 

 

 

 

3. 스코프가 왜 중요한 이유


만약 스코프가 없다면 어떻게 될까요?

 

스코프가 없다면 같은 이름을 가진 식별자들이 충돌을 일으키므로 프로그램 전체에서 하나밖에 사용할 수 없습니다.

디렉터리가 없는 컴퓨터를 생각해봅시다. 디렉터리가 없다면 같은 이름을 갖는 파일을 하나밖에 만들 수 없습니다. 스코프도 이와 같이 식별자 이름의 충돌을 방지합니다.

 

 

 

 

 

 

 

 

 

4. 스코프 유형


JavaScript의 스코프에는 1) 전역 스코프(Global Scope) 2) 지역 스코프(Function Scope) 3) 블록 스코프(Block Scope)  세 가지 유형이 있습니다 .

 

 

 

 

1. 전역 스코프(Global Scope) : 코드 어디에서든지 엑세스할 수 있습니다.

 

  • 함수나 블록(중괄호 한 쌍) 안에 있지 않은 모든 변수는 전역 범위 내에 있습니다. 
  • 전역 범위의 변수는 프로그램의 어디에서나 액세스할 수 있습니다. 

 

let greeting = 'Hello World!';
function greet() {
  console.log(greeting);
}

// Prints 'Hello World!'
greet();

 

 

 

 

 

 

 

2) 지역 스코프(Function Scope) : 함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 엑세스할 수 있습니다.

 

  • 자바스크립트는 기본적으로 함수 스코프를 따릅니다.
  • 새로운 함수가 생성될 때 마다 새로운 스코프가 발생하기 때문에 함수 몸체에 선언한 변수는 해당 함수 안에서만 접근할 수 있습니다.

 

 

 

 

지역 스코프 예제


 

if(5 > 4) {
	var secret = '12345';
}
secret // '12345'

 

  • 위 코드에서는 함수가 선언되어 있지 않기 때문에 새로운 환경, 새로운 스코프가 형성되지 않습니다.
  • 스코프가 형성되지 않으므로 동일한 실행 컨텍스트 내에서 존재합니다.
  • 그렇기때문에 어디에서나 secret변수에 대한 접근이 가능합니다.

 

 

 

 

 

function a() {
	var secret = '12345';
}
secret; //ReferenceError

 

  • 반면 이 경우는 함수 생성과 동시에 a함수에 대한 새로운 실행 컨텍스트가 생성되고,
  • 이 실행 컨텍스트 내부에 존재하는 변수환경(variable environment)에 secret변수가 저장됩니다.
  • 따라서 함수 외부에서 secret에 접근하려고 할 경우 스코프가 다르기 때문에 해당 변수에 접근이 불가능합니다.
  • 함수외부는 global scope이고, 함수 내부는 a함수의 scope인데 부모스코프는 자식스코프에서 간섭할 수 없기 때문에 접근이 불가능합니다.

 

 

 

 

 

 

function greet() {
  var greeting = 'Hello World!';
  console.log(greeting);
}

// Prints 'Hello World!'
greet();

// Uncaught ReferenceError: greeting is not defined
console.log(greeting);

 

  • 함수 내에서 선언된 변수는 함수 내에서만 엑세스 할 수 있습니다. 따라서 이를 로컬 스코프라도고 합니다.(글로벌 스코프의 반대)

 

 

 

 

 

 

 

 

3) 블록 스코프(Block Scope): 블록 {}이 생성될 때마다 새로운 스코프가 형성되는 것을 의미합니다.

 

  • 원래 자바스크립트는 함수 스코프를 따르지만, ES6에서 let const 키워드의 등장으로 블록 스코프를 형성하는 것도 가능해졌습니다.

 

 

 

 

 

 

블록 스코프 예제


 

{
  let greeting = 'Hello World!';
  var lang = 'English';
  console.log(greeting); // Prints 'Hello World!'
}

// Prints 'English'
console.log(lang);

// Uncaught ReferenceError: greeting is not defined
console.log(greeting);

 

위 코드를 보면 var 변수가 블록 외부에서 엑세스 될 수 있음을 알 수 있습니다. 반면 let 변수는 블록 외부에서 엑세스 되지 않습니다.

 

즉, var변수는 블록 스코프가 아닙니다. 

 

 

  • var => 함수스코프
  • let, const => 블록스코프

 

 

 

 

 

 

 

 

5. 스코프 체인


스코프 체인이란 각각의 스코프가 어떻게 연결(chain)되고 있는지 보여주는 것을 말합니다. 하지만 스코프 체인(scope chain)을 이해하기 위해서 먼저 자바스크립트의 실행 컨텍스트(Execution context)를 알아야 합니다.

 

 

 

 

 

 

 

 

 

6. 실행 컨텍스트(Execution context)


실행 컨텍스트(Execution context)는 우리가 작성한 코드가 실행되는 환경을 말하며, scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심원리를 말합니다.

 

그리고 이 실행 컨텍스트에는 두 개의 실행 컨텍스트가 존재합니다.

 

 

 

 

 

 

1. 글로벌 실행 컨텍스트(Global Execution Context)


 

코드가 실행되기 전에 생성이 되며, 함수 내에 없는 코드는 모두 전역 실행 컨텍스트 안에 존재합니다.

그렇기 때문에, 자바스크립트 엔진은 일부 자바스크립트 코드를 실행할 때마다 글로벌 실행 컨텍스트(Global Execution Context)를 작성합니다.

글로벌 실행 컨텍스트의 특징으로는 무조건 하나의 전역 실행 컨텍스트 만이 존재하며, 애플리케이션이 종료될 때(웹 페이지에서 나가거나 브라우저를 닫을 때)까지 유지하는 것입니다.

 

 

 

 

 

 

2. 함수 실행 컨텍스트(Functional Execution Context)


전역 실행 컨텍스트가 생성된 후, 함수가 실행(ex 호출) 될 때마다 새로운 실행 컨텍스트가 작성됩니다.

 

 

 

 

 

 

 

 

 

 

7. 실행 컨텍스트에서 스코프 체인이 작동하는 방식


실행 컨텍스트는 LIFO (Last in, First out) 구조의 스택으로, 코드 실행 중에 생성된 모든 실행 컨텍스트를 저장하는 데 사용됩니다.

실행 컨텍스트가 실행되면, 엔진이 스코프 체인을 통해 렉시컬 스코프를 먼저 파악합니다.

그러고 나서, 함수가 중첩 상태일 때 하위 함수 내에서 상위 함수의 스코프와 전역 스코프까지 참조할 수 있는데 이것을 스코프 체인을 통해 탐색하는 것입니다.

 

 

 

 

 

var v = "전역 변수";

function a() {
//function a Execution Context(EC)
	var v = "지역 변수";
    
    function b() {
    	//function b Execution Context
    	console.log(v);
    }
    
    b();
}

//Global Execution Context
a();

 

위 코드의 예제를 보면 먼저 글로벌 실행 컨텍스트(GEC)가 실행되고 스택에 쌓입니다.

그런 다음 함수 호출 순으로 실행 컨텍스트 스택에 쌓이게 되고, 가장 나중에 호출된 b() 함수가 실행 컨텍스트 안에서부터 탐색을 시작합니다.

 

 

 

 

출처: https://medium.com/@pvivek4/scope-and-execution-context-in-javascript-3b71e76cd193

 

그러면, b() 함수 안에서 변수 v를 탐색하기 시작하는데, 만약 변수 v가 없으면 b() 함수를 감싸고 있는 외부 함수 a() 함수를 탐색하기 시작합니다.

이때 a() 함수 안에 변수 v가 존재하면 안에 있는 v를 참조하게 되고, 만약 없다면 마지막으로 전역 객체를 탐색하여 v를 찾아냅니다.

 

 

 

 

 

 

 

결국 찾지 못한다면, v가 없다고 VM500:1 Uncaught ReferenceError: v is not defined라는 에러를 보게 될 것입니다.

반대로 찾았다면, 결과값은 a() 안에 변수 v가 존재하기 때문에 지역 변수라는 값이 출력이 됩니다.

하지만 만약, a() 함수 안에 변수 v를 제거한다면 전역 객체에 있는 변수 v의 값 전연 변수가 출력이 될 것입니다.

 

이런 방식으로 다른 스코프에 접근 하는 것을 스코프 체인(Scope Chain)이라고 하며, 변수를 찾아가는 과정을 스코프 체인의 Variable lookup이라고 합니다.이러한 변수 조회는 내부 스코프에서 외부 스코프로 찾아가는 방식은 유효하지만, 외부 스코프에서 내부 스코프의 변수에는 접근할 수 없다는 특징이 있습니다.

 

 

 

 

 

 

 

 

 

 

8. 스코프 체인(scope chain)을 개발자 도구로 확인하기


스코프 체인(scope chain)은 함수의 감춰진 프로퍼티인 [[Scope]]로 참조할 수 있습니다.

console.dir()을 사용하면, 개발자 도구로 쉽게 확인이 가능합니다.

 

 

b() 함수에 [[Scopes]] 속성이 존재합니다. 이것이 바로 스코프 체인(scope chain)입니다.

자기 자신의 스코프(scope)를 제외한 자신과 가장 가까운 변수 객체의 스코프 순으로 접근하는 것을 눈으로 확인할 수 있습니다.

 

 정리하자면, 자기 자신의 스코프(scope)를 제외한 자신과 가장 가까운 변수 객체의 모든 스코프들을 스코프 체인이라 할 수 있습니다.

 

 

 

 

 

 

 

 

 

 

 

* 참고 사이트에 내용을 개인적으로 복습하기 편하도록 재구성한 글입니다.
자세한 설명은 참고 사이트를 살펴보시기 바랍니다.

https://velog.io/@fromzoo/%ED%95%A8%EC%88%98%EC%8A%A4%EC%BD%94%ED%94%84-vs-%EB%B8%94%EB%A1%9D%EC%8A%A4%EC%BD%94%ED%94%84

https://blog.bitsrc.io/understanding-scope-and-scope-chain-in-javascript-f6637978cf53

https://ljtaek2.tistory.com/140

https://ljtaek2.tistory.com/145

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함