회사 코드에서 다음과 같이 선언된 함수들이 많아 궁금증이 생겨 포스팅을 하게 되었습니다.
var variable = function(){
//function
};
구체적인 예시를 들어보겠습니다.
functionOne() 과 functionTwo 에는 어떤 차이가 있을까요?
var functionOne = function(){
console.log("Hello World!");
};
function functionTwo(){
console.log("Hello World!");
}
답은 다음과 같습니다.
functionOne은 "function expression"이고
functionTwo는 "function declaration"이기 때문에
functionOne은 해당 줄이 실행되어야만 함수가 정의되고,
functionTwo는 해당 파일, 혹은 주변의 코드가 실행되면 바로 정의됩니다.
코드를 통해 보겠습니다.
functionOne(); //TypeError: functionOne is not a function
var functionOne = function(){ //익명 함수, anonymous function
console.log("Hello World!");
};
functionTwo(); //"Hello World!"
function functionTwo(){
console.log("Hello World!");
}
위와 같이 차이가 드러납니다.
function expression 방식에 대해서 조금 자세히 코드로 보자면,
abc(); //TypeError: abc is not a function
abc; //아무 일도 안 일어남
var abc = function(){
console.log("Hello World!");
//abc(); 무한루프
};
abc(); //"Hello World!";
abc 변수에 넣은 익명 함수를 호출하기 위해선 "abc();" 이렇게 코드를 작성해줘야 합니다.
또 다음과 같이 두 방식을 혼합하여 사용할 수도 있습니다.
var abc = function xyz(){};
functionOne에서와는 달리 함수에 이름을 지어줬습니다.
위 예제에서 abc는 원래대로 정의되고 Internet Explorer을 제외한 모든 브라우저에서 xyz는 해당 줄이 실행되어야만 정의됩니다. 따라서 abc, xyz 각각의 접근 범위는 다음과 같습니다.
abc(); //TypeError: abc is not a function
abc; //아무 일도 안 일어남
xyz(); //ReferenceError: xyz is not defined
var abc = function xyz(){
console.log("Hello World!");
//abc(); 무한루프
//xyz(); 무한루프
};
abc(); //"Hello World!";
xyz(); //ReferenceError: xyz is not defined
위 방식은 함수의 'name' attribute 때문에 종종 쓰인다고 합니다.
일반적으로 함수를 다음과 같이 선언하면,
function abc(){};
console.log(abc.name); // prints "abc"
'name' attribute는 당연히 우리가 명시해준 이름이 됩니다. 그런데 다음과 같이 선언하면,
var abc = function(){};
console.log(abc.name); // prints ""
이름이 없게 됩니다. 위 방식에선 anonymous function, 즉 익명 함수를 생성하여 어떤 변수에 할당해준 것이기 때문입니다.
참고로 혼합된 방식에서 name을 출력해보면,
var abc = function xyz(){};
console.log(abc.name); // Prints "xyz"
console.log(xyz.name); // ReferenceError: xyz is not defined
이렇게 됩니다.
이러한 혼합된 방식을 쓰는 또 다른 이유는, 함수 내부에서 자기 자신을 더 쉽게 호출하기 위해서입니다.
보통 변수명은 해당 변수가 어떤 역할을 하는지 직관적으로 보이도록 짓습니다.
그러다 보니 이름이 길어질 때가 있는데요, 이때 해당 함수 내부에서 자기 자신을 호출할 때 이 방법을 쓰면 더 보기 깔끔해집니다.
really.long.external.scoped.name = function shortcut(n){
// 재귀
shortcut(n - 1);
// ...
// 스스로를 콜백함수로 넘김
someFunction(shortcut);
// ...
}
Function expression 방식과 function declaration 방식의 차이에 대해 알아보았습니다.
주로 scope 가 명확히 보이는 function expression 방식을 선호한다고 합니다.
참고 : https://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname