자바스크립트는 지역 블록안에 함수를 선언하는 표준이 없다. 다음 함수의 맨 윗부부에 함수 선언문을 넣는 방법은 관례적이고 완벽히 정확하다
function f() {return 'global'}
function test(x){
function f(){ return"local"}
var result = [];
if(x){
result.push(f());
}
result.push(f());
return result;
}
test(true); //['local', 'local']
test(false); //['local', 'local']
하지만 f
를 지역 블록 안으로 이동시키면 코드는 완전히 달라진다.
function f() {return 'global'}
function test(x){
var result = [];
if(x){
function f(){ return"local"} // 런타임환경에 따라 바인딩 되는게 다르다.
result.push(f());
}
result.push(f()); //false를입력하면 선언만될뿐 할당되지 않기 때문에 에러가 난다.
return result;
}
test(true); //['local', 'local']
test(false); //에러남
아마도 [’local’,global’]
을 반환하고 그다음에 [’global’]
을 반환할 것이라고 예상했을 것이다. 다르게 보면 ['local', 'local']
. ['local', 'local']
을 예상할 수도 있다.
실제로 몇몇 자바스크립트 실행환경은 이같이 동작하지만 모든 실행환경이 이처럼 동작하는것은 아니다. 런타임시 조건적으로 어떤 포함된 블록이 실행되는지에 따라 내부 f
를 바인딩한다. (좋지 않다)
어떤 실행환경에서도 올바르게 동작하는 함수를 작성하기 위한 최선의 방법은 함수 선언문을 지역 블록이나 하위 명령에 절대 두지 않는것이다. 최선의 방법은 var 선언문과 함수 표현식을 사용하는 것이다.
function f() {return 'global'}
function test(x){
var result = [];
var g = f;
if(x){
g = function(){ return"local"} // 런타임환경에 따라 바인딩 되는게 다르다.
result.push(g());
}
result.push(g());
return result;
}
이방법은 스코프에 대한 궁금증을 해결해준다. 내부 변수는 무조건 지역변수로 바인딩되고, 할당만 조건적으로 실행된다. 따라서 결과 값은 어떤 환경에서든 동일하다.