1. 스코프란 무엇인가?
스코프는 변수와 함수가 유효한 범위를 정의하는 개념입니다. 즉, 어떤 코드 블록에서 어떤 변수와 함수를 사용할 수 있는지 결정합니다.
자바스크립트에는 두 가지 주요 스코프 유형이 있습니다.
- 블록 스코프: let과 const 키워드를 사용하여 선언된 변수의 유효 범위는 해당 변수가 선언된 블록 안에 국한됩니다.
- 함수 스코프: 함수의 매개변수와 함수 내에서 선언된 변수는 해당 함수 안에서만 유효합니다.
2. 블록 스코프
let과 const 키워드를 사용하여 선언된 변수는 블록 스코프를 따릅니다.
- let 키워드: 블록 안에서 재선언 및 재할당이 가능합니다.
- const 키워드: 블록 안에서 재선언 불가능하며, 선언 시 반드시 값을 초기화해야 합니다.
if (true) {
let message = 'Hello!';
console.log(message); // 'Hello!' 출력
}
console.log(message); // ReferenceError: message is not defined
위 예시에서 message 변수는 if 블록 안에서만 유효하며, 블록 외부에서는 사용할 수 없습니다.
3. 함수 스코프
함수의 매개변수와 함수 내에서 선언된 변수는 함수 스코프를 따릅니다.
- 함수 외부에서 선언된 변수는 함수 내에서 전역 변수로 접근 가능합니다.
- 함수 내에서 선언된 변수는 함수 외부에서는 접근 불가능합니다.
function greet(name) {
console.log(`Hello, ${name}!`);
}
const globalMessage = 'Welcome!';
greet('Alice'); // 'Hello, Alice!' 출력
console.log(name); // ReferenceError: name is not defined
위 예시에서 name 변수는 greet 함수 내에서만 유효하며, 함수 외부에서는 사용할 수 없습니다.
4. 스코프 체인
스코프 체인은 변수를 찾는 순서를 정의하는 방식입니다. 변수를 사용할 때, 다음 순서대로 해당 변수를 찾습니다.
- 현재 블록: 현재 코드 블록에서 선언된 변수를 검색합니다.
- 외부 블록: 현재 블록의 외부 블록에서 선언된 변수를 검색합니다.
- 함수 스코프: 현재 함수에서 선언된 매개변수 또는 변수를 검색합니다.
- 전역 스코프: 전역적으로 선언된 변수를 검색합니다.
변수가 여러 블록에서 동일한 이름으로 선언된 경우, 가장 가까운 블록에서 선언된 변수를 사용합니다.
5. 스코프 관련 주의 사항
- 블록 스코프를 사용하면 변수 오버라이딩 문제를 방지하고 코드 가독성을 향상시킬 수 있습니다.
- 함수 스코프를 사용하면 변수 오염 문제를 방지하고 코드 재사용성을 높일 수 있습니다.
- 스코프 체인을 이해하면 복잡한 코드에서 변수를 추적하는 데 도움이 됩니다.
- var 키워드는 블록 스코프가 아닌 함수 스코프를 따릅니다. 새로운 코드에서는 let 또는 const 키워드를 사용하는 것이 좋습니다.
global(전역) 변수과 local(지역) 변수
function print () { // 함수 블록
console.log(a);
}
{ // 블록
const a = '1';
}
var x = 'global'; // 전역(스코프) 변수
function foo () { // 지역(스코프) 함수
var x = 'function scope';
console.log(x)
}
foo(); // function scope
console.log(x); // global
var a = 1; // 전역(스코프) 변수
function print () { // 함수(스코프) 변수
console.log(a);
}
print(); // 1
var = 0;
{
var y = 1
console.log(y) // 1
}
console.log(y) // 0
let y = 0
{
let y = 1
console.log(y) // 1
}
console.log(y) // 0
스코프 체인(Scope Chain)
- 스코프 체인은 현재 스코프 레벨에서 변수가 존재하지 않는 경우 상위 스코프에서 찾는 것
- 이 찾는 과정은 스코프를 안에서 바깥쪽으로 단계적으로 탐색하는 과정이다. (내부 -> 외부 -> 전체)
- 스코프가 계층적으로 연결되어있는 것
let a = 1;
function firstFunction() {
let b = 2;
function secondFunction() {
let c = 3;
console.log(a, b, c); // 1, 2, 3 (a, b, 그리고 c에 접근 가능)
}
secondFunction();
}
firstFunction();
var x = "global x"
var y = "global y"
function outer () {
var z = "outer's local z"
console.log(x) // global x
console.log(y) // global y
console.log(z) // outer's local z
function inner () { // 중첩 함수
var x = "inner's local x"
console.log(x) // inner's local x
console.log(y) // global y
console.log(z) // outer's local z
}
inner()
}
outer()
console.log(x) // global x
console.log(z) // ReferenceError: z is not defined.
전역 스코프(Global scope)
var global = 'global';
function foo() {
var local = 'local';
console.log(global); // 'global'
console.log(local); // 'local'
}
foo();
console.log(global); // 'global'
console.log(local); // ReferenceError: local is not defined
var : 함수 레벨 스코프(Function-level scope)
var a = 10; // 전역변수
(function () {
var b = 20; // 지역변수
})();
console.log(a); // 10
console.log(b); // "b" is not defined
var x = 'global';
function foo() {
var x = 'local';
console.log(x);
}
foo(); // local
console.log(x); // global
var x = 'global';
function foo() {
var x = 'local';
console.log(x); // 'local'
function bar () { // 내부함수
console.log(x); // 'local'
}
bar();
}
foo();
console.log(x); // 'global'
var x = 10;
function foo () {
var x = 100;
console.log(x); // 100
function bar () { // 내부함수
x = 1000;
console.log(x); // 1000
}
bar();
}
foo();
console.log(x); // 10
비 블록 레벨 스코프(Non block-level scope) 전역 스코프(Global scope)
if (true) {
var x = 5;
}
console.log(x); // 5
암묵적 전역
var x = 10; // 전역 변수
function foo () {
y = 20; // 선언하지 않은 식별자(안티패턴)
console.log(x + y);
}
foo(); // 30
// 전역 변수 x는 호이스팅이 발생
x // undefined
// 전역 변수가 아니라 단지 전역 프로퍼티인 y는
// 호이스팅이 발생하지 않는다.
y // ReferenceError: y is not defined
var x = 10 // 전역 변수
function foo () {
y = 20 // 선언하지 않은 변수
console.log(x + y)
}
foo() // 30
var x = 10 // 전역 변수
function foo () {
y = 20 // 선언하지 않은 변수
console.log(x + y)
}
foo(); // 30
console.log(window.x); // 10
console.log(window.y); // 20
delete x // 전역 변수는 삭제되지 않는다.
delete y // 프로퍼티는 삭제된다.
console.log(window.x) // 10
console.log(window.y) // undefined
최소한의 전역변수 사용 - 객체 리터럴 네임스페이스
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name); // "Lee"
즉시실행함수를 이용한 전역변수 사용 억제
(function () {
var MYAPP = {};
MYAPP.student = {
name: 'Lee',
gender: 'male'
};
console.log(MYAPP.student.name); // "Lee"
}());
console.log(MYAPP.student.name); // "ReferenceError: MYAPP is not defined" - MYAPP 정의되지 않았습니다
728x90
'웹개발 > javascript' 카테고리의 다른 글
[자바스크립트] 실행 컨텍스트 (Execution Context) 이해하기 (0) | 2024.07.21 |
---|---|
[자바스크립트] 렉시컬 스코프 (Lexical Scope) 완벽 가이드 (0) | 2024.07.21 |
[자바스크립트] 리터럴 (Literal) - 숫자, 문자열, 불리언, 객체, 배열 (0) | 2024.07.21 |
[자바스크립트] this 키워드 / call(), apply(), bind() 메서드 (0) | 2024.07.21 |
[자바스크립트] 변수 const / let / var (0) | 2024.07.21 |