function double(x){return x*2}
이 함수는 선언문이 될 수도있고 기명함수 표현식이 될 수 도 있다. 선언문이 된다면 호이스팅되어 전역으로 사용될 것이다.
var f = function double(x){return x*2)
함수를 변수 f에 바인딩 한다.
물론 이름을 지정할 필요는 없다.
var f = function(x){return x*2}
기명함수 표현식은 익명함수 표현식과 달리 그 이름을 함수 내의 지역변수로 바이딩한다는 공식적인 차이점이 있다. 이특징을 재귀함수를 작성하는데 사용할 수 있다.
var f = function find(tree, key){
if(!tree){
return null
}
if(tree.key == key){
return tree.value;
}
//왼쪽에서 나오면 왼쪽 tree.value, 아니라면 오른쪽 tree.value 그것도 아니라면 null 반환
return find(tree.left, key) || find(tree.right, key);
}
내부에서 재귀함수를 사용할 때는 find
라는 이름을 사용할 수 있지만 외부에서는 사용할 수 없다.
find(myTree, "foo") //에러남
물론 외부스코프 이름을 사용할 수도 있다.
var f = function(tree, key){
if(!tree){
return null
}
if(tree.key == key){
return tree.value;
}
return f(tree.left, key)|| f(tree.right, key);
}
아니면 단순하게 선언문을 사용해도 좋다.
function find(tree, key){
if(!tree){
return null
}
if(tree.key == key){
return tree.value;
}
//왼쪽에서 나오면 왼쪽 tree.value, 아니라면 오른쪽 tree.value 그것도 아니라면 null 반환
return find(tree.left, key) || find(tree.right, key);
}
var f = find;
이러한 기명함수 표현식은 디버깅할 때 정말로 유용하다. 대부분 최신 자바스크립트 실행환경은 Error 객체를 위해 스택추적(stack trace)을 만들고 함수 표현식의 이름은 보통 스택 추적내의 엔트리로 사용된다.
기명함수 표현식의 스코프를 객체로 표현해야 한다, 이로인해 생성시 문제를 일으킬 소지가 많았다. 이 스코프객체는 그 함수의 이름을 바인딩하는 하나의 프로퍼티만을 가지지만, 당연히 Object.prototype의 프로퍼티들을 상속 받았다. 이는 함수 표현식에 이름을 짓는 것만으로 Object.prototype의 모든 프로퍼티가 해당 스코프 안으로 들어온다는 뜻이다.
Object.prototype이란 javascript에서 모든 객체가 상속받는 객체이다.
var constructor = function(){return null};
var f = function(){
return constructor();
};
f(); // {} 새로운 객체 생성 (ES3 실행 환경)
null을 반환할 것처럼 보이지만, 기명함수 표현식이 Object.prototype.constructor(즉 Object생성자 함수)를 상속하기 때문에 실제로는 새로운 객체를 만들어 낸다.
고맙게도 ES5에서는 이실수를 수정했다.
하지만 몇몇 자바스크립트 실행환경은 여전히 잘못된 스코프 방식을 고수하고 있다.
var constructor = function(){return null};
var f = function(){
return constructor();
};
f(); // {} // 표준을 따르지 않는 실행환경
함수표현식의 스코프를 객체로 오염시키는 이런문제를 피할 수 있는 최선의 방법은 Object.prototype에 새로운 프로퍼티를 절대 추가하지 않고 지역변수에 표준 Object.prototype 프로퍼티의 어떠한 이름도 사용하지 않는것이다.
var f = function g() {return 17;}
g(); //17
//물론 지금은 이러지 않음, 에러남
다음은 유명한 버그로 이는 명백히 표준을 제대로 준수하지 않는 동작이다. 이러한 불편을 막기위해서는 다음과 같은 차선책이 있다.
var f = function g() {return 17;}
var g = null;
변수를 var로 재선언하면 함수 표현식을 오류로 호이스팅하는 실행환경에서도 g가 바인딩 되는것을 보장하고, 값을 null로 지정하면 복제된 함수가 가비지컬렉션의 대상이 되게한다.
기명함수 표현식을 사용하기에는 너무 문제가 많다고 결론짓는건 당연하다. 때문에 모든 함수를 익명으로 만다는것이좋다.