함수의 유효 범위
함수의 유효 범위(function scope)
대부분의 프로그래밍 언어에서는 블록 내에서 정의된 변수를 블록 외부에서는 접근할 수 없습니다.
블록(block)이란 코드 내에서 중괄호({})로 둘러싸인 부분을 가리킵니다.
이러한 블록을 기준으로 하는 유효 범위를 블록 단위의 유효 범위라고 합니다.
하지만 자바스크립트는 다른 언어와는 달리 함수를 블록 대신 사용합니다.
자바스크립트에서 함수는 자신이 정의된 범위 안에서 정의된 모든 변수 및 함수에 접근할 수 있습니다.
'전역 함수'는 모든 전역 변수와 전역 함수에 접근할 수 있습니다.
반면, 다른 함수 내에 정의된 '내부 함수'는 그 함수의 부모 함수(parent function)에서 정의된 모든 변수 및 부모 함수가 접근할 수 있는 모든 다른 변수까지도 접근할 수 있습니다.
예제
// x, y, name을 전역 변수로 선언함.
var x = 10, y = 20;
// sub()를 전역 함수로 선언함.
function sub() {
return x - y; // 전역 변수인 x, y에 접근함.
}
document.write(sub() + "<br>");
// parentFunc()을 전역 함수로 선언함.
function parentFunc() {
var x = 1, y = 2; // 전역 변수와 같은 이름으로 선언하여 전역 변수의 범위를 제한함.
function add() { // add() 함수는 내부 함수로 선언됨.
return x + y; // 전역 변수가 아닌 지역 변수 x, y에 접근함.
}
return add();
}
document.write(parentFunc());
함수 호이스팅(hoisting)
자바스크립트에서 함수의 유효 범위라는 것은 함수 안에서 선언된 모든 변수는 함수 전체에 걸쳐 유효하다는 의미입니다.
그런데 이 유효 범위의 적용이 변수가 선언되기 전에도 똑같이 적용됩니다.
이러한 자바스크립트의 특징을 함수 호이스팅(hoisting)이라고 합니다.
즉, 자바스크립트 함수 안에 있는 모든 변수의 선언은 함수의 맨 처음으로 이동된 것처럼 동작합니다.
예제
var globalNum = 10; // globalNum을 전역 변수로 선언함.
function printNum() {
document.write("지역 변수 globalNum 선언 전의 globalNum의 값은 " + globalNum + "입니다.<br>"); // ①
var globalNum = 20; // globalNum을 지역 변수로 선언함. // ②
document.write("지역 변수 globalNum 선언 후의 globalNum의 값은 " + globalNum + "입니다.<br>");
}
printNum();
위의 예제 ①의 시점에서는 변수 globalNum가 전역 변수를 가리킨다고 생각하기 쉽습니다.
하지만 자바스크립트 내부에서는 함수 호이스팅에 의해 다음과 같이 코드가 변경되어 처리됩니다.
호이스팅 후의 코드
var globalNum = 10;
function printNum() {
var globalNum; // 함수 호이스팅에 의해 변수의 선언 부분이 함수의 맨 처음 부분으로 이동됨.
document.write("지역 변수 globalNum 선언 전의 globalNum의 값은 " + globalNum + "입니다.<br>");
globalNum = 20;
document.write("지역 변수 globalNum 선언 후의 globalNum의 값은 " + globalNum + "입니다.<br>");
}
printNum();
위의 예제 ①의 시점에서는 globalNum라는 지역 변수가 선언만 되어 있고, 아직 초기화만 안 된 상태입니다.
따라서 이때 globalNum 변수에 접근하면 아직 초기화되지 않은 변수에 접근했으므로, undefined 값을 반환하게 됩니다.
실제로 변수가 초기화되는 시점은 원래 코드에서 변수가 선언된 ②의 시점입니다.