크레도스 2014. 3. 4. 17:52

김영보님의 페북에서 퍼옴

var set = function(){
console.log(get());
function get(){return 777}
}
set();
---------------------
두 번째 줄에서 세 번째 줄에 있는 get() 함수를 호출하는 것은 일반적인 자바스크립트에서는 에러가 납니다만, 위 코드에서는 호출이됩니다. 이유는 
JS 엔진 function get()을 만나면 new Function()을 하여 Function 오브젝트를 생성합니다. 오브젝트(인스턴스)가 되어야 부가적인 처리를 할 수 있기 때문입니다. 

엔진이 set() 함수를 만나면 set 함수 코드로 실행 콘텍스트(EC)를 생성하고 EC 안으로 엔진이 이동하게 됩니다. 그리고 함수 안의 코드를 해석하기 전에 파라미터를 기준으로 EC 안의 정적 환경(Lexical Environment)을 만들고 그 안에 환경 레코드(Environment Record)를 만드는 등의 몇 가지 엔진이 해석한 내용을 기억하기 조치를 취하고 this 바인딩 레코드에 this 값을 바인딩합니다.

그리고 함수 안에서 우선 변수가 아닌 함수를 찾습니다. 즉, function get() 형태를 찾아 LE의 정적 환경 컴포넌트(Lexical Environment Record)에 등록합니다. 계속해서 함수 끝까지 function을 찾습니다. 그리고 난 후 다시 함수의 첫 라인으로 이동하여 변수를 찾아 함수와 같은 형태로 영역에 저장을 합니다.

글이 길어지니 요약하면 함수 안에서 엔진이 두 번 돈다는 점입니다. 일반적으로 위에서 아래로 한 번 도는 것으로 생각할 수 있는데 두 번 도는 메커니즘으로 인해 위의 코드에서 get() 함수가 호출될 수 있습니다.

한편 이런 형태의 코드는 개발자가 작성된 순서대로 실행되지 않으므로 문제가 될 가능성도 있고 가독성도 떨어집니다. 따라서 function get(){} 형태가 아닌 var get = function(){} 형태로 작성해야 함수가 아닌 변수로 인식되므로 함수 안에 작성한 순서대로 코드가 실행됩니다.