스코프(scope)란 무엇인가?
스코프(scope)에 대해서 알아보자.
스코프(scope)란?
- 스코프(scope)는 프로그램에서 변수나 함수가 참조될 수 있는 유효 범위를 의미함
- 스코프는 변수가 어디서 접근할 수 있는지 결정하며, 코드의 가독성과 유지보수성을 높이는데 중요함
- 스코프는 크게 전역 스코프, 함수 스코프, 블록 스코프로 나뉨
전역 스코프
2-1) 정의
함수나 블록 밖에서 선언된 변수는 전역 스코프를 가지며, 프로그램 전체에서 접근이 가능하다. 예) 전역 변수
2-2) 특징
어디에서나 접근이 가능하지만, 전역 변수가 많아지면 의도치 않게 재선언이 되어 유지보수가 어려울 수 있음
그렇기에 전역 변수는 재선언이 불가능하게 let으로 선언하자!
- 어디에서나 접근 가능
-
var
로 선언한 전역 변수는 재선언이 가능하여 변수가 재선언되어 유지보수가 어려워질 수 있음 -
let
으로 선언한 전역 변수는 재선언이 불가능하여 변수가 덮어씌어지는 걸 방지할 수 있음
2-3) 전역 스코프 예시
let globalLet = "Hello World"; // 전역 변수 선언
function test01() {
// 함수 안에서도 찾을 수 있음
console.log(globalLet); // "Hello World"
}
test01();
console.log(globalLet); // "Hello World"
함수 스코프
정의
함수 내에서 선언된 변수는 해당 함수 내에서만 유효함
3-1) 특징
함수가 종료되면 변수는 더 이상 접근할 수 없으며 함수 내부에서 선언하지 않고 사용하면 암묵적으로 전역 변수가 될 수 있음 (var)
유지보수 측면에서 var
는 사용하지 않는게 좋다!
- 함수가 종료되면 변수는 더 이상 접근할 수 없음
- 함수가 호출되며 생성된 변수는 함수가 종료되면 메모리에서 해제되어 더 이상 접근이 불가함
- 함수 내부에서 변수를 선언하지 않고 사용하면 암묵적으로 전역 변수가 될 수 있음
- JavaScript에서
var
를 사용할 때, 변수 선언 없이 값을 할당하면 암묵적으로 전역 변수가 될 수 있음
- JavaScript에서
- 변수
var
는 쓰지 말자!
3-2) 함수 스코프 예시
function test02_01() {
let num = 1;
console.log(num); // 1
}
test02_01();
console.log(num); // num을 찾을 수 없음
function test02_02() {
var num = 2;
if (true) {
var num = "hi"; // 같은 함수 스코프 내에서 num가 재선언되고 재할당된다. (고로 var은 쓰지말자)
console.log(num); // "hi"
}
console.log(num); // "hi"
}
test02_02();
함수 외부에서 접근
함수 스코프의 변수는 함수가 종료되면 더 이상 접근이 불가능하지만 접근하는 방법이 무엇인지 궁금해서 찾아보았는데, 함수 반환 값과 클로저가 있었다.
함수 반환 값 (return)
함수 반환 값은 함수가 시행된 후 반환하는 결과값을 의미하며 함수가 호출하면, 함수 내부의 return
문을 통해 외부로 값을 전달한다.
- 단순한 데이터 반환: 함수가 실행된 후 계산된 값을 반환함
- 명시적 반환: 함수가 반환하는 값은 함수 호출 시 명시적으로 반환됨
- 상태 유지 불가: 반환된 값은 함수의 실행이 완료되면 그 상태를 유지하지 않으며 함수가 종료된 후, 반환된 값은 외부에서 사용되지만 함수 내의 상태를 기억하지 않음
// 예시 1
function createNum() {
let num = 0; // 함수 내에서만 유효한 변수
return function () {
num += 1;
return num;
};
}
const number = createNum();
console.log(number()); // 1
console.log(number()); // 2
// 예시 2
function add(x, y) {
return x + y;
}
const sum = add(3, 5); // sum은 8
console.log(sum); // 8
클로저(Closure)
클로저는 함수가 다른 함수의 내부 변수를 기억
하는 함수이며 내부 함수가 외부 함수의 변수에 접근할 수 있도록 해줌
- 상태 유지: 클로저는 외부 함수의 변수를 기억하고, 외부 함수가 실행된 후에도 그 변수를 유지함
- 함수의 반환값으로 사용: 클로저는 내부 함수로서 외부 함수의 변수에 접근할 수 있는 함수다. 내부 함수가 외부 함수의 스코프를 기억함
function test() {
let a = "Hello";
function innerFunc() {
console.log(a); // "Hello" (외부 함수의 변수 접근)
}
return innerFunc();
}
const inner = test();
inner(); // "Hello" 함수 외부에서 내부 변수에 접근함
함수 반환 값과 클로저의 차이점
- 목적
- 함수 반환 값: 함수가 실행된 후 특정 값을 반환하여 외부에서 사용할 수 있도록함.
- 클로저: 함수가 외부 함수의 변수를 기억하고, 해당 변수에 대한 상태를 유지하며 외부 함수가 종료된 후에도 계속 접근할 수 있게함
- 상태 유지
- 함수 반환 값: 반환된 값은 함수 종료 후에 상태를 유지하지 않음. 함수 실행이 끝나면 함수 내부의 상태는 잃어버림
- 클로저: 클로저는 외부 함수의 변수에 대한 참조를 유지하며 함수가 종료된 후에도 해당 변수의 상태를 유지하고 수정할 수 있음
- 사용 방식
- 함수 반환 값: 계산된 값을 외부로 전달하기 위해 사용
- 클로저: 내부 함수가 외부 함수의 상태를 유지하고, 특정 데이터나 상태를 캡처하여 관리하기 위해 사용
결론
- 함수 반환 값은 단순히 계산된 값을 외부로 전달할 때 사용된다. 상태 유지가 필요 없고, 함수의 결과를 단순히 전달하면 되는 경우에 적합함
- 클로저는 함수가 내부 상태를 유지하며 외부 함수의 변수에 접근할 필요가 있을 때 사용됨
블록 스코프
3-1) 정의
블록({}) 내에서 선언된 변수는 해당 블록 내에서만 유효함
3-2) 특징
- 블록이 종료되면 더 이상 접근할 수 없음
- 상위 블록에서 선언된 변수는 하위 블록에서 사용 가능함
- 상위 블록에서 선언한 변수를 하위 블록에서 선언하면 새로운 변수로 인식함
3-3) 함수 스코프 예시
if (true) {
let x = 1;
console.log(x); // 1
}
console.log(x); // x를 찾을 수 없음
let y = 1; // 상위 블록
if (true) {
y = 2;
console.log(y); // 2
}
console.log(y); // 2;
for (let i = 0; i < 10; i++) {
console.log(i); // 0,1,2,3...
}
console.log(i); // i를 찾을 수 없음
주의할점
블록 스코프
- 변수를 블록 밖에서 사용하려면 블록 밖에서 전역으로 선언해야함
- 블록 내에서 변수를 재선언하면 블록 내에서만 새로운 변수로 인식됨
함수 스코프
- 함수 내에서 변수를 선언하지 않고 사용하면 암묵적으로 전역 변수가 될 수 있음 (var)
- 함수 내 변수는 함수가 종료되면 더 이상 접근이 불가능함
- 접근이 가능하게 하려면 함수 반환값과 클로저를 이해하고 사용해야함
마무리
스코프는 변수나 함수 유효 범위를 결정하기에 각 스코프를 이해하고 올바르게 사용할 수 있어야겠다.
그렇지 않을 경우 코드의 가독성,유지보수,안정성이 모두 떨어지는 결과를 초래할 것이며 지켜진다면 효율적인 코드를 작성할 수 있을 것 같다.
함수 반환값과 클로저는 조금 더 이해해보도록 공부해봐야겟다.