-
[JavaScript] 자바스크립트의 스코프와 호이스팅: 개념과 작동 원리2024년 12월 23일
- 유니얼
-
작성자
-
2024.12.23.:39
728x90JavaScript를 깊이 이해하기 위해서는 스코프(Scope)와 호이스팅(Hoisting)의 개념을 명확히 이해하는 것이 중요합니다. 이 글에서는 변수의 접근 범위를 정의하는 스코프와, JavaScript의 독특한 변수 처리 방식인 호이스팅에 대해 상세히 설명합니다.
1. 스코프(Scope)
스코프는 변수나 함수가 정의되고 접근할 수 있는 범위를 의미합니다. 특정 코드에서 변수에 접근할 수 있는지는 그 변수의 스코프에 의해 결정됩니다.
스코프의 종류
1. 글로벌 스코프
정의: 함수나 블록 외부에서 선언된 변수는 글로벌 스코프를 가집니다.
특징:
- 애플리케이션의 모든 코드에서 접근 가능합니다.
- 글로벌 변수는 어디에서나 접근할 수 있지만, 지나치게 사용하면 다른 코드와 충돌할 가능성이 높아 권장되지 않습니다.
예시:
var globalVar = "I am global"; function printGlobalVar() { console.log(globalVar); // "I am global" } printGlobalVar();
2. 함수 스코프
정의: 함수 내부에서 선언된 변수는 함수 스코프를 가집니다.
특징:
- 해당 함수 내부에서만 접근 가능하며, 함수 외부에서는 접근할 수 없습니다.
- **지역 변수(Local Variable)**라고도 불립니다.
예시:
function myFunction() { var localVar = "I am local"; console.log(localVar); // "I am local" } myFunction(); console.log(localVar); // ReferenceError: localVar is not defined
3. 블록 스코프 (ES6 이후)
정의: {}로 묶인 블록 안에서 선언된 변수는 블록 스코프를 가집니다.
특징:
- let과 const 키워드로 선언된 변수에만 적용됩니다.
- 블록 내부에서만 접근할 수 있으며, 블록 외부에서는 접근할 수 없습니다.
- 함수 또한 블록 스코프를 따릅니다.
예시:
if (true) { let blockVar = "I am block scoped"; console.log(blockVar); // "I am block scoped" } console.log(blockVar); // ReferenceError: blockVar is not defined
2. 스코프 체인(Scope Chain)
스코프 체인은 특정 변수를 찾기 위해 자바스크립트가 스코프 계층을 탐색하는 과정을 말합니다.
작동 원리:
- 변수를 참조할 때, 현재 스코프에서 변수를 찾습니다.
- 만약 현재 스코프에 변수가 없다면, 상위 스코프를 순차적으로 탐색합니다.
- 글로벌 스코프까지 탐색해도 변수를 찾지 못하면 ReferenceError가 발생합니다.
예시:
var globalVar = "Global"; function outerFunction() { var outerVar = "Outer"; function innerFunction() { var innerVar = "Inner"; console.log(innerVar); // "Inner" console.log(outerVar); // "Outer" console.log(globalVar); // "Global" } innerFunction(); } outerFunction();
3. 호이스팅(Hoisting)
호이스팅은 JavaScript에서 변수와 함수 선언이 실행 컨텍스트의 최상단으로 끌어올려지는 동작을 말합니다.
- 변수나 함수의 선언이 실행 전에 스코프의 최상단으로 끌어올려지는 것처럼 동작합니다.
- 다만, 실제로 코드를 이동시키는 것은 아니며, 인터프리터가 이를 미리 처리합니다.호이스팅의 작동 방식
1, var 변수:
- var로 선언된 변수는 선언과 초기화가 함께 호이스팅됩니다.
- 초기 값은 undefined로 설정되며, 이후 코드에서 재할당됩니다.
예시:
console.log(a); // undefined var a = 10; console.log(a); // 10
2, let, const 변수:
- let과 const로 선언된 변수는 선언과 초기화가 분리되어 처리됩니다.
- 초기화가 이루어지기 전에 변수를 참조하면 **ReferenceError**가 발생합니다.
- 이는 일시적 사각지대(TDZ, Temporal Dead Zone) 때문입니다.
예시:
console.log(b); // ReferenceError: Cannot access 'b' before initialization let b = 20;
3, 함수 선언:
- 함수 선언문은 전체가 호이스팅됩니다. 따라서 선언된 함수는 선언 위치와 상관없이 호출할 수 있습니다.
- 예시:
greet(); // "Hello!" function greet() { console.log("Hello!"); }
4, 함수 표현식:
- 함수 표현식은 호이스팅되지 않습니다. 선언 전에 호출하면 오류가 발생합니다.
예시:
console.log(greet); // undefined var greet = function() { console.log("Hi!"); }; greet(); // "Hi!"
4. 일시적 사각지대(TDZ)
일시적 사각지대는 변수 선언이 호이스팅되었지만 초기화가 이루어지기 전까지의 구간을 의미합니다.
특징:
- TDZ에서는 변수를 참조할 수 없으며, 이를 시도하면 ReferenceError가 발생합니다.
- 변수 선언이 스코프의 시작 지점에서 이루어지더라도 초기화가 이루어지기 전까지는 접근할 수 없습니다.
예시:
{ console.log(x); // ReferenceError: Cannot access 'x' before initialization let x = 10; console.log(x); // 10 }
호이스팅이 일어나는 경우와 그렇지 않은 경우
호이스팅이 일어나는 경우
- var 키워드로 선언된 변수.
- 함수 선언문.
호이스팅이 일어나지 않는 경우
- let과 const 키워드로 선언된 변수.
- 함수 표현식.
전체 예제 코드
// 스코프 'strict mode' // 나이 계산 함수 function calcAge(birthYear) { const age = 2025 - birthYear; // 현재 연도에서 태어난 연도를 뺀 값으로 나이 계산 function printAge() { const output = `${firstName}님, 당신은 ${age}살이고 ${birthYear}년도에 태어났습니다.`; console.log(output); // 계산된 나이 출력 if (birthYear >= 1981 && birthYear <= 1996) { // 밀레니얼 세대 여부 확인 var millenial = true; // 밀레니얼 여부를 저장하는 변수 (var로 선언) const firstName = "Kevin"; // if 블록 내 지역 변수 const str = `${firstName}, 당신은 밀레니얼입니다.`; // console.log(str); // 밀레니얼 여부 메시지 출력 // 블록 내 함수 선언 function add(a, b) { return a + b; // 두 값을 더하는 함수 } } // console.log(millenial); // var는 함수 스코프이므로 접근 가능 // console.log(add(2, 3)); // add 함수 호출 가능 여부 확인 } printAge(); // printAge 함수 호출 return age; // 계산된 나이를 반환 } const firstName = 'Owen'; // 글로벌 스코프 변수 calcAge(1990); // 나이 계산 함수 호출 // 변수 선언 방식의 차이 var me = 'Owen'; // var로 선언한 글로벌 변수 let job = 'engineer'; // let으로 선언한 글로벌 변수 const year = 1993; // const로 선언한 글로벌 변수 // 함수 선언 방식 function addDecl(a, b) { return a + b; // 함수 선언식 (호이스팅 적용) } const addExpr = function (a, b) { return a + b; // 함수 표현식 (호이스팅 적용되지 않음) }; const addAwwor = (a, b) => a + b; // 화살표 함수 if (!numProducts) { // numProducts 값이 falsy면 실행 deleteShoppingCart(); // 쇼핑카트 삭제 함수 호출 } var numProducts = 10; // var로 선언된 변수 (호이스팅됨) function deleteShoppingCart() { console.log("모든 상품 삭제"); // 메시지 출력 }
결론
- 스코프는 변수가 접근할 수 있는 범위를 결정하며, 글로벌, 함수, 블록 스코프로 나뉩니다.
- 스코프 체인은 변수를 찾기 위해 상위 스코프를 탐색하는 과정입니다.
- 호이스팅은 선언문을 스코프의 최상단으로 끌어올리는 동작처럼 보이게 만듭니다.
하지만 초기화 시점과 TDZ의 개념을 이해해야 관련 오류를 방지할 수 있습니다.
JavaScript의 스코프와 호이스팅은 코드의 작동 방식을 이해하는 데 핵심적인 역할을 합니다. 이를 명확히 이해하면 오류를 예방하고 더 효율적인 코드를 작성할 수 있습니다.
반응형다음글이전글이전 글이 없습니다.댓글