티스토리 뷰

지난번에 못 다쓴 자바스크립트의 파싱에 대해서 좀 더 얘기를 해볼까 한다.

앞서 말했듯이 자바스크립트는 파싱단계를 통해 소스를 재정렬하게되는데 var 변수와 함수를 함수(실행컨텍스트) 최상단으로 끌어올려 선언하고 런타임에 그 값을 정의하게된다.

변수에 대해서는 지난번 글에 꽤 설명을 했었다.

그럼 함수는 어떻게 될까?


이걸 설명하기에 앞서 함수 선언 부분을 봐보자.

보통은 이런식으로 함수를 선언한다.


function func(){}


근데 이미 알고있는 분들도있겠지만 함수는 이런식으로도 표현이 가능하다.


var func = function(){}


위쪽을 '함수 선언식' 아랫쪽을 '함수 표현식'이라고 말하는거같은데 이게 공식적인 용어인지는 잘 모르겠다.

여튼 어떤식으로 선언하든 호출은 동일하게 한다.


func();


이게 의미하는게 무엇일까?

결국 함수도 자바스크립트 내부적으로는 '변수'로 관리한다는 뜻이다.

변수와 함수가 내부적으로 동일하게 취급된다는 점이다. 이 말은 즉 함수와 변수의 이름이 같으면 서로 덮어쓴다는 거고 자바에서는 상상도 할 수 없는일이다.

이런식으로 선언하게되면 제일 마지막 변수가 함수를 덮어쓰게된다.


function func(){}

var func = 5;


이제 좀 머릿속이 복잡해질수있다. 좀 더 정확히 말하자면 함수를 선언하게되면 내부적으로 var 변수로 관리하게된다.

이 소스를 다시보자


function func(){}


이 소스가 실행되면 자바스크립트 내부적으로 변수와 마찬가지로 func라는 변수가 선언되고 undefined로 정의가된다. 그리고 런타임에 함수를 '참조' 하게된다.

그럼 위에서 선언식과 표현식이라고 표현한 두 표현식의 차이를 보자


1.

alert(func());

alert(func);

function func(){ return 5; }


2.

alert(func());

alert(func);

var func = function(){ return 5; }


파싱단계에서 undefined로 정의되고 런타임에 함수를 참조하기 전에 호출을 하고있다.

undefined는 함수가 아니기때문에 호출부분에서는 에러가 나야정상이다.

그리고 에러가 나는순간 아래코드를 실행하지않지만 실행된다고 가정을하면 호출부분 아래 func는 undefined가 출력이되어야 할것이다.

일단 두개를 테스트해보면 2번은 우리가 예상한대로 실행이 될것이다.

첫번째 alert()에서 에러가 날것이고, 그부분을 주석처리하고 실행하면 두번째 alert()은 undefined가 출력된다.

그런데 첫번째는 예상과 다르게 실행된다. 첫번째 alert()은 함수가 리턴하는 5가 출력되고 두번째 alert()은 함수의 내부 소스가 출력된다.

어떻게 이렇게 된걸까?

 

지난번 포스팅에 파싱때 재정렬을 통해 최상위 부분으로 올라와 선언되는것은 2가지로했다. 그 2가지는 var변수와 함수선언문이다. 그런데 지금 포스팅을 통해 우리는 함수도 표현식에 차이는 있지만 결국은 var 변수로 관리한다는것을 알게되었다. 그렇다면 첫번쨰 포스팅도 'var변수와 함수선언문이 재정렬된다.' 라고 표현할게 아니라 'var변수만이 재정렬된다.' 라고 표현해야 좀 더 정확한 표현이 아닐까?

아니다. var 변수와 함수선언문은 재정렬되는것에 차이가 있다. 1, 2 각각 의 소스를 우리가 파싱해보자

 

1.

var func;

func = function(){ return 5; }

alert(func());

alert(func);

 

2.

var func;

alert(func());

alert(func);

func = function(){ return 5; }

 

함수 선언문과 함수 표현식이라는 두자기 용어가 있다고 말했지만 어쨋든 결국은 익명함수를 변수에 저장하는 방식인셈이다. 익명함수는 함수선언문과 마찬가지의 표현이기때문에 2번의 파싱을 좀 더 정확하게 표현하자면 이렇다.

 

var func;

function(){ return 5; } // 이때 함수의 참조공간(주소)을 할당받음.

alert(func());

alert(func);

func = ;// 위에서 할당받은 주소를 func변수에 대입함.

위에서 별로 중요하지않게 쓰고 넘어갔지만 함수 선언식과 함수 표현식의 차이는 함수 선언식의 경우 엔진이 파싱을 할때부터 애초에 얘가 함수를 담을 변수라는걸 알게끔 표현하는것이고, 함수 표현식의 경우 함수를 생성해 변수에 담는다는 개념이다.

 

선언식이나 표현식이나 파싱단계에서 재정렬을 통해 var 변수로 선언이 되고 함수도 생성이 된다는것은 동일하다.

다만 선언식같은 경우 애초에 함수를 담을 것이라는걸 엔진차원에서 알고있기때문에 재정렬된 최상위 단에서 변수에 담아주고 표현식은 런타임시 변수에 값을 대입하는 구문에 오기전까지는 그것을 알지못해 변수와 함수 모두 생성은 해놨지만 대입을 하지않고 있다가 해당구문에 와서 대입을 하는것이다.

*이때 함수의 공간을 할당하고 그 주소를 참조하는것뿐이지. 이때 함수가 구현되지는 않는다. 함수는 함수 영역대로 해당 함수가 호출될때 전역과 마찬가지로 파싱과 런타임의 단계를 갖게된다. 때문에 함수 내부에 명백한 에러코드가 있다고하더라도 그 함수를 호출하지않으면 소스실행과정에서 에러는 뜨지않는다.


그렇기때문에 함수선언 위에서 함수를 호출하게되어도 에러없이 이미 참조하고 있는 주소로가서 함수를 파싱하고 실행(런타임)하게 되는것이다.

 

2번의 포스팅을 통해 var 변수와 함수의 파싱과 런타임에 대해 알아봤다.

사실 이정도만 이해하고 있어도 실행단계에서 에러가 나는거에 대해선 대부분 처리가 가능하다. 자바를 기준으로는 도저히 에러가 날 부분이 없는데 왜 날까? 라고 생각하고 몇시간씩 보낼수도있는걸 우리는 이미 파싱을 통해 함수 제일 아랫부분에 선언되어있는 var 변수가 함수시작부터 에러를 낼수도있는 여건이 된다는걸 알고있지않은가?

 

파싱과정에 소스 재정렬을 '호이스팅' 이라고 표현하기도한다.

단어뜻부터 끌어올린다는 뜻을 내포하기있기에 사실 개념만 정확히 이해하고있다면 큰 무리가 있는 단어는 아니지만, 공식적인 단어는 아닌것으로 알고있다. 그렇기에 파싱 설명에서 굳이 호이스팅이라는 단어는 사용하지않았다.

자바스크립트는 사실 함수와 객체가 전부라고해도 무리는 없다고 생각한다.

그리고 객체는 var 변수에 저장하게되기때문에 자바스크립트를 코딩하면서 선언하게되는건 var 변수와 함수가 전부다.

그런데 자바스크립트의 파싱을 공부하면서 함수도 결국은 var 변수라는걸 알게되었고 var 변수의 파싱, 런타임에 대해서도 알게되었다.


이로써 자바스크립트가 돌아가는 큰틀에 대해서 어느정도 감을 잡았다고 할 수 있다.

파싱 포스팅은 이것으로 마치겠다.

'Java Script & HTML' 카테고리의 다른 글

#04. JavaScript의 함수  (0) 2015.08.28
#03. JavaScript의 연산자  (0) 2015.08.27
#02. JavaScript의 Parsing - 02  (0) 2015.08.26
#01. JavaScript의 Parsing - 01  (0) 2015.08.24
브라우저 탐색  (0) 2015.07.24
javascript AJAX  (0) 2015.01.15
댓글
댓글쓰기 폼