JavaScript Scope
JavaScript Scope: 변수의 범위와 접근성
JavaScript Scope(스코프)는 변수나 함수가 어디에서 접근할 수 있는지를 정의하는 개념입니다. JavaScript에서 스코프는 코드의 실행 컨텍스트와 밀접한 관련이 있으며, 각 변수는 선언된 위치에 따라 유효 범위가 결정됩니다. 스코프는 프로그램의 가독성과 유지 보수성에 중요한 역할을 하며, 변수를 적절하게 관리하는 데 도움이 됩니다.
이 가이드는 JavaScript에서 스코프의 종류와 스코프 규칙을 설명합니다.
1. 스코프의 종류
JavaScript에서는 주로 **전역 스코프(Global Scope)**와 **지역 스코프(Local Scope)**로 나뉩니다. 지역 스코프는 **함수 스코프(Function Scope)**와 **블록 스코프(Block Scope)**로 다시 세분화됩니다.
1.1. 전역 스코프 (Global Scope)
전역 스코프에 선언된 변수는 어디에서든지 접근 가능하며, 프로그램 전체에서 사용할 수 있습니다. 함수나 블록 외부에서 선언된 변수는 전역 변수가 됩니다.
1.1.1. 예시
let globalVar = "I am global";
function printGlobalVar() {
console.log(globalVar); // 전역 변수에 접근 가능
}
printGlobalVar(); // 출력: I am global
console.log(globalVar); // 출력: I am global
1.2. 지역 스코프 (Local Scope)
지역 스코프는 특정 블록이나 함수 내부에서만 유효한 변수를 정의하는 스코프입니다. 지역 변수는 해당 스코프 내에서만 접근할 수 있습니다.
1.2.1. 함수 스코프 (Function Scope)
함수 내부에 선언된 변수는 함수 스코프에 속하며, 함수 외부에서는 접근할 수 없습니다.
function localScopeExample() {
let localVar = "I am local";
console.log(localVar); // 함수 내부에서 접근 가능
}
localScopeExample(); // 출력: I am local
console.log(localVar); // 오류: localVar는 함수 외부에서 접근 불가
1.2.2. 블록 스코프 (Block Scope)
let
, const
키워드로 선언된 변수는 블록 스코프를 가지며,
**중괄호({}
)**로 묶인 블록 내에서만 유효합니다. 이는 if
문,
for
문, while
문 등의 블록 안에서도 적용됩니다.
if (true) {
let blockScoped = "I am block scoped";
console.log(blockScoped); // 블록 내에서 접근 가능
}
console.log(blockScoped); // 오류: blockScoped는 블록 외부에서 접근 불가
1.3. 함수 스코프 vs 블록 스코프
var
키워드로 선언된 변수는 함수 스코프를 가지며, 블록 외부에서도 접근할 수 있습니다.- *
let
*과 **const
*는 블록 스코프를 가지며, 블록 외부에서는 접근할 수 없습니다.
1.3.1. var
와 블록 스코프
if (true) {
var functionScoped = "I am function scoped";
}
console.log(functionScoped); // 출력: I am function scoped (블록 외부에서 접근 가능)
1.3.2. let
과 블록 스코프
if (true) {
let blockScoped = "I am block scoped";
}
console.log(blockScoped); // 오류: blockScoped는 블록 외부에서 접근 불가
2. 중첩 스코프 (Nested Scope)
JavaScript에서는 스코프가 중첩될 수 있습니다. 즉, 함수나 블록 내에서 다른 함수나 블록이 존재할 때, 내부 스코프는 외부 스코프에 접근 가능하지만, 외부 스코프는 내부 스코프에 접근할 수 없습니다.
2.1. 예시: 중첩된 스코프
function outer() {
let outerVar = "I am from outer";
function inner() {
let innerVar = "I am from inner";
console.log(outerVar); // 내부 함수에서 외부 함수의 변수에 접근 가능
}
inner();
console.log(innerVar); // 오류: 외부 함수에서 내부 함수의 변수에 접근 불가
}
outer();
- 내부 스코프는 외부 스코프에 접근할 수 있습니다.
- 외부 스코프는 내부 스코프에 접근할 수 없습니다.
3. 전역 객체 (Global Object)
전역 스코프에서 선언된 변수는 **전역 객체(Global Object)**의 속성이 됩니다. 브라우저 환경에서는 전역 객체가 window
객체이며, 전역
변수는 window
객체의 속성으로 저장됩니다.
3.1. 예시: 전역 객체
var globalVar = "I am global";
console.log(window.globalVar); // 출력: I am global
4. let
, const
, var
의 차이
JavaScript에서 변수를 선언할 때 사용하는 var
, let
,
**const
**는 각각의 스코프 규칙과 특성이 다릅니다.
4.1. var
의 특징
- 함수 스코프를 가집니다.
- 블록 스코프를 가지지 않으며, 함수 내 어디서든 접근 가능합니다.
- 변수 호이스팅(hoisting)으로 인해 선언 이전에 사용할 수 있지만, 초기화되지 않은 상태입니다.
4.2. let
의 특징
- 블록 스코프를 가집니다.
- 변수 호이스팅이 발생하지만, **TDZ(Temporal Dead Zone)**에 의해 선언 전에 사용할 수 없습니다.
4.3. const
의 특징
- 블록 스코프를 가집니다.
- 상수로, 재할당이 불가능합니다.
- 참조형 데이터(객체, 배열)일 경우, 값은 변경할 수 있지만 참조는 변경할 수 없습니다.
4.3.1. const
참조형 데이터 예시
const arr = [1, 2, 3];
arr.push(4); // 배열 요소 추가는 가능
console.log(arr); // 출력: [1, 2, 3, 4]
arr = [5, 6]; // 오류: const 변수는 새로운 배열로 재할당할 수 없음
5. 호이스팅 (Hoisting)
JavaScript는 변수와 함수 선언을 호이스팅하여 코드의 최상단으로 끌어올립니다. 하지만, var
,
let
, **const
**의 호이스팅 방식은 서로 다릅니다.
5.1. var
호이스팅
- *
var
*로 선언된 변수는 호이스팅되지만, 초기화는 나중에 이루어집니다. 따라서 선언 전에 접근할 수 있으나, 초기화 전까지는 **undefined
*입니다.
console.log(a); // 출력: undefined (호이스팅 발생)
var a = 10;
5.2. let
과 const
호이스팅
- *
let
*과 **const
*도 호이스팅되지만, **TDZ(Temporal Dead Zone)**에 의해 선언 전에 접근할 수 없습니다. 따라서 선언 전에 접근하려고 하면 오류가 발생합니다.
console.log(b); // 오류: b는 초기화되기 전에 접근할 수 없음
let b = 10;
6. 스코프 체인 (Scope Chain)
JavaScript에서 변수를 찾을 때, 현재 스코프에서 해당 변수를 찾지 못하면 외부 스코프로 이동하여 변수를 찾습니다. 이를 **스코프 체인(Scope Chain)**이라고 부릅니다.
6.1. 예시: 스코프 체인
let globalVar = "global";
function outer() {
let outerVar = "outer";
function inner() {
let innerVar = "inner";
console.log(globalVar); // 출력: global (외부 스코프에서 찾음)
console.log(outerVar); // 출력: outer (외부 함수 스코프에서 찾음)
}
inner();
}
outer();
요약
- *스코프(Scope)**는 변수와 함수가 어디에서 접근 가능한지를
정의합니다.
- 전역 스코프는 프로그램 전체에서 접근 가능하며, 지역 스코프는 함수나 블록 내에서만 접근할 수 있습니다.
- 블록 스코프는
let
, **const
*에서 적용되며, **var
*는 블록 스코프를 따르지 않고 함수 스코프를 따릅니다. - 호이스팅은 변수와 함수 선언을 코드의 최상단으로 끌어올리지만,
let
, **const
*는 TDZ에 의해 선언 전에 접근할 수 없습니다. - 스코프 체인을 통해 변수를 찾으며, 내부 스코프는 외부 스코프에 접근할 수 있지만, 외부 스코프는 내부 스코프에 접근할 수 없습니다.
JavaScript에서 스코프를 적절히 이해하고 사용하면 변수의 유효 범위를 관리하고, 코드의 안정성과 유지 보수성을 높일 수 있습니다.