본문 바로가기
Web

[JavaScript] Scope란 무엇인가?

by DuncanKim 2022. 7. 3.
728x90

[JavaScript] Scope란 무엇인가?

자바스크립트를 하다 보면 스코프라는 단어를 많이 접할 수 있다.

스코프는 우리말로 '범위'라는 뜻을 가지고 있다. 즉, 스코프는 변수에 접근할 수 있는 범위를 의미한다.

global(전역)과 local(지역)이 그 예가 될 것이다. 전역 스코프는 전역에 선언되어 있어 어느 곳에서든지 해당 변수에 접근할 수 있다는 의미이고, 지역 스코프는 해당 지역에서만 접근할 수 있어 지역을 벗어난 곳에서는 참조 또는 접근 할 수 없다는 의미이다. 함수 스코프가 지역 스코프의 한 예이다.

 

이것은 자바의 특수한 변수 체계 때문에 더욱 알아야 되는 개념인데, 아래에서는 var, let의 차이점을 중심으로 Scope가 무엇인지를 알아볼 것이다.

 

 

1. 레벨 스코프

var a = 1; // 전역 스코프
	function print() { // 지역(함수) 스코프
		var a = 111;
		console.log(a);
	}

print(); // 111
console.log(a); // 1

print() 함수의 경우 지역 내에서 111이라는 값이 주어져 있다. 그렇기 때문에 111이 출력되어 나오게 된다.

그렇지만 전역에 선언된 console.log(a); 같은 경우, 지역의 함수를 참조할 수 없다. 전역에 있는 var a = 1; 을 참조하게 되는 것이다.

 

자바스크립트는 다른 언어에 비해 특이한 점이 있는데, 바로 '함수 레벨 스코프'를 따르고 있다는 점이다.

또한 자바스크립트에는 var, let, const라는 변수 타입이 존재한다는 점이다.

 

함수 레벨 스코프(Function-level scope)함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다. var 키워드가 이를 따른다.

<함수 레벨 스코프, var의 특징>

var a = 123; // 전역
console.log(a); // 콘솔출력 : 123

{
var a = 456; // 블록 안이어도 전역으로 인식
}
console.log(a); // 콘솔출력 : 456

 

한편, 블록 레벨 스코프(Block-level scope)모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다. let 키워드가 이를 따른다.

<블록 레벨 스코프, let의 특징>

let a = 123; // 전역

{
  let a = 456; // 지역
  let b = 456; // 지역
}// 지역에 있기 때문에, 동일한 이름을 갖는 let a를 한번 더 선언할 수 있다.
// let은 일반적으로 변수를 중복해서 선언할 수 없다.
// var는 중복해서 변수를 여러 번 선언할 수 있다.

console.log(a); // 123
console.log(b); // ReferenceError: bar is not defined

 

 

2. 호이스팅(Hoisting)

 

호이스팅(Hoisting)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다. 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.

 

하지만 var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다. 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

 

console.log(a); // undefined
var a;

console.log(b); // Error: Uncaught ReferenceError: bar is not defined
let b;

 

var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화(초기화 단계)한다. 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다. 이러한 현상을 변수 호이스팅(Variable Hoisting)이라 한다.

 

 

// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.
console.log(a); // undefined

var a;
console.log(a); // undefined

a = 1; // 할당문에서 할당 단계가 실행된다.
console.log(a); // 1

 

 

 

 

참고 :  https://poiemaweb.com/es6-block-scope

 

 

 

728x90

댓글