JS 호이스팅!
호이스팅(Hoisting)
앞서 var변수를 얘기하면서, 호이스팅에 대해서 거론하였습니다.
호이스팅이란 선언부를 유효범위의 최상위로 끌어올리는 것을 말합니다.
<br/>
호이스팅은 변수 호이스팅 / 함수 호이스팅으로 구분할 수 있습니다.
<br/>
먼저 변수 호이스팅은 다음 코드를 볼 수 있습니다.
function foo(){
var a = 10;
var a = 20;
console.log(a); // 20
}
a변수를 두번 선언함에도 에러가 발생하지 않습니다.
이유는 호이스팅이 선언부를 function-scope의 최상위로 끌어올렸기 때문입니다.
<br/>
내부적으로는 다음과 같이 읽을것 입니다.
function foo(){
var a;
a = 10;
a = 20;
console.log(a); //20
}
<br/>
또 다음과 같은 코드도 동일하게 동작합니다.
function foo(){
var a = 10;
if(true){
var a = 20;
}
console.log(a);
}
foo();
<br/>
호이스팅되어서 다음과 같이 내부적으로 동작합니다.
function foo(){
var a;
a = 10;
if(true){
a = 20;
}
console.log(a); // 20
}
foo();
<br/>
let, const는 호이스팅을 하지 않습니다.
따라서 동일한 변수를 두번선언한 경우 에러를 출력할 것입니다.
<br/>
<br/>
다음은 함수 호이스팅입니다.
함수 호이스팅은 함수선언을 최상위로 끌어올리는것을 말합니다.<br />
! 함수선언식만이 호이스팅을 합니다.
<br/>
함수 선언식과 함수표현식은 다음과 같이 구분합니다.
/** 함수 선언식 **/
//Function Declarations
function foo() {
console.log('hello');
}
/** 함수 표현식 **/
//anonymous function expression
var foo = function() {
console.log('hello');
};
//named function expression
var foo = function foo() {
console.log('hello');
};
// 자기호출함수, self invoking function expression
(function foo() {
console.log('hello');
})();
<br/>
다음 코드를 보면 함수호이스팅을 볼 수 있습니다.
foo();
function foo(){console.log("hello")} //hello
foo 함수가 후에 선언되었음에도, 에러를 출력하지 않고 정상 수행됩니다.
자바스크립트 엔진이 구동 시 최우선으로 함수선언식을 수집하여 최상위 Scope로 끌어올리기 때문입니다.
<br/>
그럼 다음 코드를 볼까요.
function foo(){
function bar() {
console.log('hello');
}
return bar();
function bar() {
console.log('world');
}
}
foo();
// world
결과는 world를 출력합니다.
호이스팅에 의해 함수선언식이 최우선적으로 수집되어 최상위 Scope로 끌어올려졌기 때문입니다.
<br/>
function foo(){
var bar= function() {
console.log('hello');
};
return bar();
var bar = function() {
console.log('world');
};
}
foo();
// hello
하지만 다음코드는 hello를 출력합니다.
bar 함수가 함수표현식으로 선언되었기 때문입니다.
따라서 호이스팅 하지 않았고, 후에 선언된 bar 함수를 읽지 않았기 때문입니다.
<br />
참고
<a href="http://insanehong.kr/post/javascript-function/">Function Declarations(함수선언) vs Function Expressions(함수표현)</a>