Function Declarations vs Function Expressions - Lee-hyuna/33-js-concepts-kr GitHub Wiki
์๋ฌธ : https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
์งง์ ํด์ฆ๋ฅผ ์์ํ๊ฒ ์ต๋๋ค. ๊ฐ๊ฐ์ ์ผ์ด์ค์์ alert์๋ ๋ฌด์์ด ์์๊น์?
Question 1:
function foo(){
function bar() {
return 3;
}
return bar();
function bar() {
return 8;
}
}
alert(foo());
function foo(){
var bar = function() {
return 3;
};
return bar();
var bar = function() {
return 8;
};
}
alert(foo());
alert(foo());
function foo(){
var bar = function() {
return 3;
};
return bar();
var bar = function() {
return 8;
};
}
function foo(){
return bar();
var bar = function() {
return 3;
};
var bar = function() {
return 8;
};
}
alert(foo());
๋ง์ฝ 8,3,3์ ๋๋ตํ ์ ์๊ฑฐ๋ [Type Error: bar is not a function]์ด ๋์จ๋ค๋ฉด ์ด ๊ธ์ ์ฝ์ด์ผ ํฉ๋๋ค. (์ค์ ๋ก ์ด๋ ๋๊ตฌ๋ ์ฝ์ด๋ ๋ฉ๋๋ค.๐)
ํจ์ ์ ์ธ์์ ๋ณ์ ํ ๋น์ ์๊ตฌํ์ง ์๊ณ ๋ช ๋ช ๋ ํจ์ ๋ณ์๋ฅผ ์ ์ ํฉ๋๋ค. ํจ์ ์ ์ธ์ ๋ ๋ฆฝ ์คํํ ๊ตฌ๋ฌธ์ผ๋ก ๋ฐ์ํ๋ฉฐ ๋น-ํจ์ ๋ธ๋ก ๋ด์ ์ค์ฒฉ๋ ์ ์์ต๋๋ค. ๋ณ์ ์ ์ธ์ ํ์ ๋ผ๊ณ ์๊ฐํ๋ฉด ๋์์ด ๋ฉ๋๋ค. ๋ณ์ ์ ์ธ์ด โvarโ๋ก ์์ํ๋ ๊ฒ์ฒ๋ผ ํจ์ ์ ์ธ์์ โfunctionโ์ผ๋ก ์์ํด์ผ ํฉ๋๋ค.
function bar() {
return 3;
}
ECMA 5 (13.0)์ javascript function Identifier ( FormalParameterListopt ) { FunctionBody } ๋ฌธ๋ฒ์ผ๋ก ์ ์ ๋์ด ์์ต๋๋ค.
ํจ์ ์ด๋ฆ์ scope๋ด์์ ๋ณผ ์ ์์ผ๋ฉฐ, scope๋ ๋ถ๋ชจ ์ ๋๋ค. (๊ทธ๋ ์ง ์์ผ๋ฉด ๋๋ฌ ํ ์ ์์ผ๋ฏ๋ก ์ข์ต๋๋ค.)
function bar() {
return 3;
}
bar() //3
bar //function
ํจ์ ํํ์์ ๋ ๋ง์ ํํ์ ๋ฌธ๋ฒ(์ผ๋ฐ์ ์ผ๋ก ๋ณ์์ ํ ๋น)์ ์ผ๋ถ๋ก ์ ์ ํฉ๋๋ค. ํจ์ ํํ์์ ํตํด ์ ์๋ ํจ์์ ์ด๋ฆ์ ์ต๋ช ์ผ๋ก ์ง์ ํ ์ ์์ต๋๋ค. ํจ์ ํํ์์ โfunctionโ ์ผ๋ก ์์ํ๋ฉด ์๋ฉ๋๋ค. (๋ฐ๋ผ์ ์๋์ ์ง์ ํธ์ถ์ ์์ ์์ ๊ดํธ)
//anonymous function expression
var a = function() {
return 3;
}
//named function expression
var a = function bar() {
return 3;
}
//self invoking function expression
(function sayHello() {
alert("hello!");
})();
ECMA 5 (13.0)์ function Identifieropt ( FormalParameterListopt ) { FunctionBody } ๋ฌธ๋ฒ์ผ๋ก ์ ์ ๋์ด ์์ต๋๋ค. โfunctionโ์ผ๋ก ์์ํ์ง ์๋ ํํ์ ๋ฌธ๋ฒ์ด ํฌํจ๋์ด์ง ์๊ตฌ์ฌํญ์ผ๋ก ์ธํด ๋ถ์์ ํ๋ค๊ณ ๋๋ ์ ์๋ค. (though this feels incomplete since it omits the requirement that the containing syntax be an expression and not start with โfunctionโ>์์ญ)
ํจ์ ์ด๋ฆ(์กด์ฌ ํ๋ ๊ฒฝ์ฐ)์ ํด๋น scope ๋ฐ์์ ๋ณผ ์ ์์ต๋๋ค. (ํจ์ ์ ์ธ์๊ณผ ๋์กฐ๊ฐ ๋๋ค.)
๋๋ก๋ ํจ์ ์ ์ธ์ ์ํ ๊ฐ๋ช ์ ๋๋ค. ๊ทธ๋ฌ๋ kangax๊ฐ ์ง์ ํ๋ฏ์ด mozilla์์ ํจ์๋ฌธ์ ํจ์ ์ ์ธ์ ํ์ฅ์ผ๋ก ํจ์ ์ ์ธ๋ฌธ์ ํจ์๋ฌธ์ ํ์ฉ๋๋ ๋ถ๋ถ ์ด๋์์๋ ํจ์ ์ ์ธ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. (in mozilla a Function Statement is an extension of Function Declaration allowing the Function Declaration syntax to be used anywhere a statement is allowed.>์ด๋ป๊ฒ ์ค๋ช ์ ํ๋ ๊ฒ์ด ๋ ๋์๊น..) ์์ง ํ์ค์ด ์๋๋ฏ๋ก production development์ ๊ถ์ฅ๋์ง ์์ต๋๋ค.
์ข์ต๋๋ค. ์ง๋ฌธ 1์ ํจ์ ์ ์ธ์ ์ฌ์ฉํฉ๋๋ค. ์ฆ hoisted๋จ์ ์๋ฏธํฉ๋๋ค.
Ben Cherry์ ๋ฐ์ด๋ ๊ธฐ์ฌ๋ฅผ ์ธ์ฉํฉ๋๋ค. โFunction declarations and function variables are always moved (โhoistedโ) to the top of their JavaScript scope by the JavaScript interpreterโ
ํจ์ ์ ์ธ์ด ์๋จ์ผ๋ก ์ด๋ํ๊ฒ ๋๋ฉด ์ ์ฒด ํจ์ ๋ณธ๋ฌธ์ด ์๋จ์ผ๋ก ์ด๋ํ๊ฒ ๋๋ฏ๋ก ์ธํฐํ๋ฆฌํฐ๊ฐ ์ง๋ฌธ1์ ์ฝ๋๊ฐ ๋๋ ํ์๋ ๋ค์๊ณผ ๊ฐ์ด ์คํ๋ฉ๋๋ค.
//**Simulated processing sequence for Question 1**
function foo(){
//define bar once
function bar() {
return 3;
}
//redefine it
function bar() {
return 8;
}
//return its invocation
return bar(); //8
}
alert(foo());
ํ์ง๋ง...ํ์ง๋ง..์ฐ๋ฆฌ๋ ํญ์ ๋ฐํ๋ฌธ์ด ๋๋ฌ ํ ์ ์๋ค๋ ๊ฒ์ ๋ฐฐ์์์ต๋๋ค.
Javascript์คํ์๋ Context(ECMA 5๊ฐ LexicalEnvironment, VariableEnvironment, ThisBinding์ผ๋ก ๋ถ๋ฆฌ๋๋ ๊ฒ) ๋ฐ Process (์์๋๋ก ํธ์ถ๋ ๋ช ๋ น๋ฌธ ์ธํธ)๊ฐ ์์ต๋๋ค. ์คํ scope๊ฐ ์ ๋ ฅ๋๋ฉด ์ ์ธ์ด VariableEnvironment์ ๊ธฐ์ฌํฉ๋๋ค. Context์ Process๋ return๊ณผ ๊ฐ์ Statement์ ๊ตฌ๋ณ๋๊ณ , process์ ๊ท์น์ ๋ํ ์ ์ฉ์ ๋ฐ์ง ์์ต๋๋ค.
๊ทธ๊ฒ์ ํํ์์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ํด์ฆ 2๋ฒ์งธ์ ์ฒซ๋ฒ์งธ ํํ์์ ๋ณด๊ฒ ์ต๋๋ค.
var bar = function() {
return 3;
};
์ผ์ชฝ์ var bar์ ๋ณ์ ์ ์ธ ์ ๋๋ค. ๋ณ์ ์ ์ธ์ ์๋จ์ผ๋ก ์ด๋์ด ๋์์ง๋ง ํ ๋น ํํ์์ ๊ทธ๋ ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ bar๊ฐ ์๋จ์ผ๋ก ์ฌ๋ผ๊ฐ๋ฉด ์ธํฐํ๋ฆฌํฐ๋ ์ด๊ธฐ์ var bar = undefined์ ์ค์ ํฉ๋๋ค. ํจ์ ์ ์ ์์ฒด๋ ํธ์ด์คํธ ๋์ง ์์ต๋๋ค. (ECMA 5 12.2 ์์ ์ด๊ธฐํ๊ฐ ์ด๋ค์ง ๋ณ์์๋ ๋ณ์๊ฐ ๋ง๋ค์ด์ง ๋๊ฐ ์๋๋ผ VariableStatement๊ฐ ์คํ์ด ๋ ๋ AssignmentExpressionr๊ฐ์ด ํ ๋น๋ฉ๋๋ค.)
๋ฐ๋ผ์ ํด์ฆ 2์ ์ฝ๋๋ ๋ณด๋ค ์ง๊ด์ ์ธ ์์๋ก ์คํ์ด ๋ฉ๋๋ค.
//**Simulated processing sequence for Question 2**
function foo(){
//a declaration for each function expression
var bar = undefined;
var bar = undefined;
//first Function Expression is executed
bar = function() {
return 3;
};
// Function created by first Function Expression is invoked
return bar();
// second Function Expression unreachable
}
alert(foo()); //3
์ข์ต๋๋ค. ๊ทธ ๋ง์ด ๋ง๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๊ฑด ๊ทธ๋ ๊ณ ์ง๋ฌธ 3์ ๋ํด์ ํ๋ ธ๋๋ฐ Firebug์์ error๊ฐ ๋ฐ์ ํ์ต๋๋ค.
HTML ํ์ผ์ ์ ์ฅํ๊ณ Firefox์์ ์คํํด๋ณด์ธ์. ๋๋ IE8, Chrome ๋๋ Safari ์ฝ์์์ ์คํํด๋ณด์ธ์. ๋ถ๋ช ํ Firebug ์ฝ์์ โglobalโ scope์์ ์คํ๋ ๋ ํจ์ ํธ์ด์คํ ์ ์ฐ์ตํ์ง ์์ต๋๋ค. (์ค์ ๋ก โglobalโ์ด ์๋์ง๋ง ํน๋ณํ โFirebugโ์ scope - โFirebugโ์ ์ฝ์์์๋ โthis == windowโ์ด ์คํ๋ฉ๋๋ค.)
ํด์ฆ 3์ ํด์ฆ 1๊ณผ ์ ์ฌํ ๋ ผ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ์ด๋ฒ์๋ hoisted๋ foo ํจ์ ์ ๋๋ค.
๊ฑฐ์. ํธ์ด์คํ ์ด ๋ชจ๋ ์์ผ๋ฉด TypeError๋ โbar not definedโ๊ฐ ๋๊ณ โbar not a functionโ์ด ์๋๋๋ค. ํจ์ ํธ์ด์คํ ๊ฐ ์์ง๋ง ๊ฐ๋ณ ํธ์ด์คํ ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ bar๋ ์์ ์ ์ธ๋์์ง๋ง ๊ฐ์ ์ ์๋์ง ์์ต๋๋ค. ๋ชจ๋ ๊ฒ์ ๋ค๋ฅธ ์์๋ก ์คํํฉ๋๋ค. (Everything else runs to order. ์ฌ๊ธฐ์์ order ํด์์...?)
//**Simulated processing sequence for Question 4**
function foo(){
//a declaration for each function expression
var bar = undefined;
var bar = undefined;
return bar(); //TypeError: "bar not defined"
//neither Function Expression is reached
}
alert(foo());
ํจ์ ์ ์ธ์์ ํจ์๊ฐ ์๋ ๋ธ๋ก(ex:if) ๋ด์์ ๊ณต์์ ์ผ๋ก ๊ธ์ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ๋ ์ด๋ฅผ ํ์ฉํ๊ณ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ํด์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด Firefox 3.6์ ๋ค์ ์ฝ๋ ์ค๋ํซ์ ํจ์ ์ ์ธ์ ํจ์ ๊ตฌ๋ฌธ์ผ๋ก ํด์ํ๋ฏ๋ก x๋ ์ ์๋์ง ์์์ผ๋ฏ๋ก ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ IE8, Chrome 5 ๋ฐ Safari 5์์๋ ํจ์ x๊ฐ ๋ฐํ๋ฉ๋๋ค.(ํ์ค ํจ์ ์ ์ธ์์์ ์์ ํ๋๋ก)
function foo() {
if(false) {
function x() {};
}
return x;
}
alert(foo());
ํจ์ ์ ์ธ์ด ์ฉ์๊ฐ ๋๋ค๊ณ ์ฃผ์ฅํ ์ ์์ต๋๋ค. ์ ์ธ๋๊ธฐ ์ ์ ํจ์๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๋ฉด ํธ์ด์คํ ์ด ๋ช ๋ น์ ์์ ํ ํ์ ๋ฌธ์ ๋ ๋ฐ์ํ์ง ์๊ณ ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฐ ์ข ๋ฅ์ ์ฉ์๋ ๋จ๋จํ ์ฝ๋ฉ์ ๊ถ์ฅํ์ง ์์ผ๋ฉฐ ์ฅ๊ธฐ์ ์ผ๋ก ์๋ง ๊ทธ๊ฒ์ ๋ง๊ธฐ๋ณด๋ค๋ ๋๋ผ์์ ์กฐ์ฅํ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค. ๊ฒฐ๊ตญ ํ๋ก๊ทธ๋๋จธ๋ ์ด์ ์ ๋ฐ๋ผ ํน์ ์์๋ก ๋ช ๋ น๋ฌธ์ ์ ๋ ฌํฉ๋๋ค.
์ด๋ป๊ฒ ์์ จ๋์?
a) ํจ์ ์ ์ธ์ Java ์คํ์ผ ๋ฉ์๋ ์ ์ธ์ ๋ชจ๋ฐฉํ๋ ค๋ ์๋์์ง๋ง Java ๋ฉ์๋๋ ๋งค์ฐ ๋ค๋ฅธ ์กด์ฌ๋ผ๊ณ ๋๋๋๋ค. Javascript ํจ์์์๋ ๊ฐ์ด ์๋ํ ์ด์์๋ ๊ฐ์ฒด ์ ๋๋ค. Java ๋ฉ์๋๋ ๋ฉํ ๋ฐ์ดํฐ ์ ์ฅ ๊ณต๊ฐ์ ๋๋ค. ๋ค์์ ์ค๋ํซ์ ๋ชจ๋ ํจ์๋ฅผ ์ ์ํ์ง๋ง ํจ์ ํํ์๋ง์ด ์ฐ๋ฆฌ๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์์์ ์์ํฉ๋๋ค.
//Function Declaration
function add(a,b) {return a + b};
//Function Expression
var add = function(a,b) {return a + b};
b) ํจ์ ํํ์์ ๋ณด๋ค ๋ค์ํฉ๋๋ค. ํจ์ ์ ์ธ์์ "๋ช ๋ น๋ฌธ"์ผ๋ก๋ง ์กด์ฌํ ์ ์์ต๋๋ค. ํ์ฌ ๋ณ์๊ฐ ๋ถ๋ชจ ๋ณ์์ธ ๊ฐ์ฒด ๋ณ์๋ฅผ ๋ง๋๋ ๊ฒ๋ฟ ์ ๋๋ค. ๋ฐ๋๋ก ํจ์ ํํ์(์ ์์ ์ํ)์ ๋ ํฐ ๊ตฌ์กฐ์ ์ผ๋ถ ์ ๋๋ค. ์ต๋ช ํจ์๋ฅผ ๋ง๋ค๊ฑฐ๋ ํจ์๋ฅผ ํ๋กํ ํ์ ์ ํ ๋นํ๊ฑฐ๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ์์ฑ์ผ๋ก ํ ๋นํ๋ ค๋ฉด ํจ์ํํ์์ด ํ์ํฉ๋๋ค. curry ๋๋ compose์ ๊ฐ์ ๊ณ ์ฐจ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉํ์ฌ ์๋ก์ด ํจ์๋ฅผ ๋ง๋ค ๋๋ง๋ค ํจ์ ํํ์์ ์ฌ์ฉํฉ๋๋ค. ํจ์ ํํ์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๋ถ๋ฆฌํ ์ ์์ต๋๋ค.
//Function Expression
var sayHello = alert.curry("hello!");
์ผ๋ฐ์ ์ผ๋ก ํจ์ ํํ์์ ์ํด ์์ฑ๋ ํจ์๋ ์ด๋ฆ์ด ์ง์ ๋์ด ์์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์ ํจ์๋ ์ต๋ช ์ด๋ฉฐ, ์ค๋๋ ์ ์ด๋ฆ ์๋ ํจ์์ ๋ํ ์ฐธ์กฐ ์ผ๋ฟ์ ๋๋ค.
var today = function() {return new Date()}
์ด๊ฒ ์ ๋ง ์ค์ํ ๊น์? Nick Fitzgerald๊ฐ ์ต๋ช ํจ์๋ก ๋๋ฒ๊น ์ ํ๋ ๊ฒ์ ์ข์ ๊ฐ์ ์ค ์ ์๋ค๊ณ ์ง์ ํ ๊ฒ์ฒ๋ผ ๋ง์ ๋๋ค. ๊ทธ๋ ๋ช ๋ช ๋ ํจ์ ํํ์์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ ๊ฒ์ ์ ์ํฉ๋๋ค.
var today = function today() {return new Date()}
๊ทธ๋ฌ๋ Asen Bozhilov๊ฐ ์ง์ ํ ๋๋ก(๊ทธ๋ฆฌ๊ณ Kangax์ ๋ฌธ์) NFE๋ IE 9 ํ์ ๋ธ๋ผ์ฐ์ ์์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ์ง ์์ต๋๋ค.
์๋ชป ๋์ฌ์ง ํจ์ ์ ์ธ์์ ์คํด์ ์์ง๊ฐ ์์ ์ ์์ผ๋ฉฐ ๋ฉด์์ ํ ๋น๋ ํจ์ ํํ์์ ๋์ ์ฌ์ฉํ ์ ์๋ ์ํฉ์ด ๊ฑฐ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํจ์ ์ ์ธ์์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ ํจ์ ์ ์ธ์์ด ์ํ ๋ฒ์๋ฅผ ๋งจ ์์ ๋์ผ๋ฉด ํผ๋์ ์ต์ํ ํ ์ ์์ต๋๋ค. ๋๋ if ์ ์ธ๋ฌธ์ ํจ์ ์ ์ธ์์ ๋์ง ์์ ๊ฒ์ ๋๋ค.
์ด ๋ชจ๋ ๊ฒ์ ๋งํ๋ฉด ํจ์ ์ ์ธ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํ๋นํ ์ํฉ์์ ์ค์ค๋ก๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ๊ด์ฐฎ์. ๊ท์น์ ์๊ฒฉํ ์ค์๋ ์ํํ๋ฉฐ ๋๋ก๋ ์๋ค์ด์ง ์ฝ๋๊ฐ ๋ฉ๋๋ค. ํจ์ฌ ๋ ์ค์ํ ๊ฒ์ ์ค์ค๋ก ์์ ์ ์ ๋ณด์ ์ ๊ฐํ ๊ฒฐ์ ์ ๋ด๋ฆด ์ ์๋๋ก ๊ฐ๋ ์ ์ดํดํ๋ค๋ ๊ฒ์ ๋๋ค. ์ด ๊ธ์ด ๋์์ด ๋๊ธธ ๋ฐ๋๋๋ค.