-
[JavaScript] 스코프Language/JavaScript 2024. 11. 24. 00:20728x90
1) 스코프
스코프란 자바스크립트에서 변수, 함수, 객체 등이 접근할 수 있는 범위를 의미한다.
코드 구조와 변수 선언 방식에 따라서 결정되고, 스코프를 이해하면 변수가 어디에서 접근 가능한지, 변수간의 충돌을 어떠게 피할 수 있는지를 알 수 있다.스코프는 크게 전역 스코프와 지역 스코프로 나뉘는데, 앞서 말했듯 변수나 함수 객체 모두 스코프를 갖고 있기 때문에 변수가 전역 스코프를 가지면 전역 변수라고 볼 수 있고, 변수가 특정 스코프에서만 사용될 수 있다면 지역 변수라고 볼 수 있다.
1-1) 스코프의 종류
전역 스코프(Global Scope)
- 프로그램 전체에서 접근 가능한 범위이다.
var
,let
,const
등의 키워드를 사용하지 않고 선언된 변수 또는 전역 객체(window
등)에 직접 할당된 변수는 전역 변수로 간주된다
전역 객체에 대해서는 나중에 더 알아보자
var globalVar = "나는 전역 변수"; function printGlobal() { console.log(globalVar); // 접근 가능 } printGlobal(); // "나는 전역 변수"
지역 스코프(Local Scope)
- 함수나 블록 내부에서의 범위라고 볼 수 있다.
- 함수 내부에 선언된
var
,let
,const
변수들은 함수 스코프를 가진다 let
과const
는 블록 스코프를 가지며, 중괄호 안에서만 유효하다.
스코프에는 이렇게 두 가지 말고도 더 자세한 개념들이 있다.
함수 스코프(Function-level Scope)
- 함수 내에서 선언된 변수가 함수 전체에서 유효하며, 함수 외부에서 접근할 수 없는 스코프이다.
var
키워드는 함수 스코프를 따른다. 즉, 함수 내에서 선언된var
변수는 블록을 무시하고 함수 전체에서 접근 가능하다.
function example() { if (true) { var functionScoped = "나는 함수 스코프"; } console.log(functionScoped); // "나는 함수 스코프" (블록 밖에서도 접근 가능) } example(); console.log(functionScoped); // ReferenceError: functionScoped is not defined
블록 스코프(Block-level Scope)
- 중괄호 '{ }'로 구분된 코드 블록 내에서 선언된 변수만 해당 블록에서 유효함을 말하는 스코프이다.
let
과const
키워드는 블록 스코프를 따른다. 즉, 변수가 선언된 블록 외부에서는 접근이 불가능하다.
{ let blockScoped = "나는 블록 스코프"; const anotherBlockScoped = "나도 블록 스코프"; console.log(blockScoped); // "나는 블록 스코프" } console.log(blockScoped); // ReferenceError: blockScoped is not defined
스크립트 스코프(Script Scope)
- 스크립트 스코프는 브라우저 환경에서의 전역 스코프를 말한다.
- ES6 이후
let
과const
로 선언된 전역 변수는 더 이상 진정한 전역 객체(window)의 속성이 아니며, 스크립트 범위에서만 유효하다. var
로 선언된 변수는 여전히 전역 객체의 속성이 된다.
정적 스코프(Lexical Scope)
- 렉시컬 스코프는 변수가 코드 작성 시점의 문맥에 따라 접근 가능한 스코프를 결정하는 방식을 의미한다.
- 자바스크립트는 렉시컬 스코핑을 따르는 언어이다. 즉, 함수 정의 위치에 따라 변수의 유효 범위가 정해진다. 실행 시점에 따라 바뀌지 않는다.
let outerVar = "나는 외부 변수"; function outerFunction() { let innerVar = "나는 내부 변수"; function innerFunction() { console.log(outerVar); // "나는 외부 변수" (외부 스코프 접근 가능) console.log(innerVar); // "나는 내부 변수" (렉시컬 환경에서 찾음) } innerFunction(); } outerFunction();
1-2) 스코프 체이닝
앞서 말했듯 자바스크립트는 렉시컬 스코프 개념에 기반을 하고 있기 때문에, 함수나 블록 내부에서 변수를 찾을 때 스코프 체인을 통해 탐색한다.
스코프 체이닝의 동작 원리
- 현재 스코프에서 변수를 탐색한다
변수 참조가 발생하면, 자바스크립트는 먼저 현재 스코프에서 해당 변수를 찾는다. - 상위 스코프로 이동한다
현재 스코프에서 변수를 찾지 못하면 바로 상위 스코프로 이동해 변수를 탐색한다. - 전역 스코프까지 이동한다:
계속해서 상위 스코프로 이동하며, 최종적으로 전역 스코프에서 변수를 탐색한다. - 변수를 찾지 못하면 오류가 발생한다
모든 스코프를 탐색한 후에도 변수를 찾지 못하면ReferenceError
가 발생한다.
스코프 체인의 구조
스코프 체인은 여러 스코프를 연결한 체인 구조를 형성한다.
예를 들어, 함수 내부에서 변수를 참조할 때 다음 순서로 탐색한다:함수 내부 스코프 → 함수가 선언된 외부 스코프 → … → 전역 스코프
예제: 스코프 체이닝
let globalVar = "전역 변수"; function outerFunction() { let outerVar = "외부 변수"; function innerFunction() { let innerVar = "내부 변수"; console.log(innerVar); // "내부 변수" (현재 스코프에서 찾음) console.log(outerVar); // "외부 변수" (상위 스코프에서 찾음) console.log(globalVar); // "전역 변수" (전역 스코프에서 찾음) } innerFunction(); } outerFunction();
innerVar
:innerFunction
의 내부 스코프에서 선언되어 바로 찾음.outerVar
:innerFunction
의 내부 스코프에 없으므로 상위 스코프인outerFunction
에서 찾음.globalVar
:outerFunction
에도 없으므로 전역 스코프에서 찾음.
스코프 체인의 중요성
렉시컬 스코프 개념과 관계성
자바스크립트는 렉시컬 스코프(정적 스코프)를 따르기 때문에 함수가 선언된 위치에 따라 스코프 체인이 결정된다. 실행 시점이 아니라 정의 시점에서 스코프 체인이 형성된다.클로저와의 관계성
클로저는 스코프 체인을 활용해 외부 함수의 변수에 접근할 수 있는 메커니즘이다.function outer() { let outerVar = "외부 변수"; return function inner() { console.log(outerVar); // "외부 변수" (스코프 체인으로 접근) }; } const innerFunc = outer(); innerFunc();
클로저에 대해서는 나중에 더 자세히 알아보도록 하자
스코프 체인과 변수 숨기기
상위 스코프와 하위 스코프에 동일한 이름의 변수가 있을 경우, 가장 가까운 스코프의 변수가 사용된다.let value = "전역 변수"; function example() { let value = "지역 변수"; console.log(value); // "지역 변수" (가장 가까운 스코프에서 찾음) } example(); console.log(value); // "전역 변수"
스코프 체인의 한계
다른 스코프로 직접 접근이 불가하다
하위 스코프에서 상위 스코프는 접근 가능하지만, 상위 스코프에서 하위 스코프는 접근할 수 없다.
function example() { let innerVar = "내부 변수"; } console.log(innerVar); // ReferenceError: innerVar is not defined
성능 이슈
스코프 체인 탐색은 상위로 계속 이동하기 때문에, 너무 깊은 체인은 성능 저하를 유발할 수 있다.따라서 변수의 사용 범위를 최소화하고, 불필요한 전역 변수 사용을 피하는 것이 중요하다.
더 알아볼만한 것
- TDZ(Temporal Dead Zone)에 대하여
- 호이스팅(Hoisting)에 대하여
- 전역 객체(Global Object)에 대하여
- 클로저(Closure)에 대하여
'Language > JavaScript' 카테고리의 다른 글
[MJDD] 1장 프로그래밍 (0) 2024.11.28 [MJDD] 들어가며 (0) 2024.11.26 [JavaScript] 연산자 (0) 2024.11.23 [JavaScript] 데이터 타입 (0) 2024.11.21 [JavaScript] 변수 (2) 2024.11.19