티스토리 뷰

자바스크립트는 한번에 모든 소스를 컴파일하는 컴파일 언어가 아니라 한줄 한줄 실행하는 인터프리터 언어이다.

때문에 자바스크립트는 컴파일이라는 단어보다 파싱이라는 단어가 좀 더 정확한 단어라고 할수있다.

소스를 한번 파싱한 후 한줄씩 런타임으로 진행하게되는데 파싱단계에서 소스가 재정렬이 되게된다.

 

*이때 파싱과 런타임은 '함수' 단위로 실행되게된다. 좀 더 어려운 말을 쓰면 실행컨텍스트라고 하는데 함수라고 생각하면 이해가 쉽다. 그리고 최상위 레벨인 전역공간 역시 전역함수 내부에서 실행중이라고 생각하자.

 

이때 재정렬 되면서 함수단위 최상위로 올라오게되는것들이

 

1. var 변수선언

2. 함수선언

 

이다.

가령 예를들게되면

 

alert("선언 전 => " + num1);

var num1 = 5;

alert("선언 후 => " + num1);

 

이런 소스가 있다고 했을때 보통의 자바개발자들이라면 굳이 자바가 아니라도 hello world라도 찍어봤다는 개발자들이라면 에러를 예상할것이다. 하지만 이 소스는 에러가 나지않을 뿐더러 위 alert()과 아래 alert()은 서로 다른 값을 출력하게된다.

 

위에서 파싱단계에서 재정렬되는것은 var변수와 함수선언이라고 했다.

3줄밖에 안되는 소스지만 하나하나 자바스크립트의 엔진입장이 되어 파싱을 해보자.

 

var num1;

alert("선언 전 => " + num1);

num1 = 5;

alert("선언 후 => " + num1);

 

첫번째 줄의 alert() 은 알림창을 띄우는 '함수'다. 그럼 지금 사용된

alert("선언 전 => " + num1);

은 최소 var 변수 선언은 아니라는걸 알수있다.

그럼 함수 선언일까? 대답은 NO.

 

var func = function(){}

function func(){}

 

함수 선언은 위와 같은 2가지 문법이고 alert() 은 함수선언이 아니라 함수 호출부분이다.

그렇기때문에 파싱단계에서 재정렬되지않는다.

그럼 두번째줄

 

var num1 = 5; 를 보자

어떻게봐도 이건 var 변수 선언이다. 위에서 말한대로 파싱단계에서 선언부분이 최상단으로 올라오게되고 초기화부분까지 올라오는것은 아니기에 '5'가 아닌 'undefined'로 정의된다.

그리고 세번째줄은 첫번째줄과 같은 함수호출이니 신경안쓰고 넘어간다.

파싱이 끝나면 런타임단계로 넘어가 소스가 실행되게된다.

 

그럼 첫번째줄의 함수가 호출되게된다. 헌데 내부에 num1이라는 변수를 호출하고있고 현재 num1은 파싱단계에서 undefined로 정의된 이후 아직 건드린적이 없다.

그때문에 첫번째 alert()은 undefined가 출력되게된다.

 

그리고 두번째에 undefined가 담겨있던 num1에 5가 정의되게되고 그로인해 세번째 alert() 에서는 5가 출력되게된다.

 

물론 의도치않은 값(undefined)이 출력이 됐지만 여튼 자바스크립트에서는 변수 초기화를 아래에서 하고 그 위에서 호출하더라도 에러없이 출력이 되는걸 확인할수있었다.

 

명심해야할건 var로 선언된 변수만이 파싱단계에서 undefined로 초기화 된다는 것이다.

 

1.

console.log(num1);

console.log(num2);

var num1 = 5;

num2 = 10;

 

2.

var num1 = 5;

num2 = 10;

console.log(num1);

console.log(num2);

 

결과가 어떻게 나올까?

기존 자바개발자라면 2번도 에러가 날것이라고 예상할수있다. 하지만 실행시켜보면 알겠지만 오히려 1번이 에러가 나고 2번이 에러없이 정상 실행되는것을 확인할 수 있다.

 

var가 없이 선언된 변수는 파싱단계에서는 그냥 넘어가고 런타임단계에서 '전역' 변수로 정의된다.

 

1.

function setName(_name){

var myname = _name;

}

setName("LichKing");

console.log(myname);

 

2.

function setName(_name){

myname = _name;

}

setName("LichKing");

console.log(myname);

 

1번 setName()의 name은 setName() 함수 내부에서만 유효하다.

때문에 전역단계에 myname이란 변수가 없으니 에러가 발생한다.

허나 2번 같은경우 setName()의 함수파싱단계에서 var변수나 함수선언 부분이 없으므로 그냥 지나가게되고 런타임시 myname이라는 변수가 '전역'레벨의 변수로 선언되고 _name의 값으로 초기화되게된다.

때문에 전역에서 myname을 호출하게되면 에러없이 "LichKing"이라는 문자열이 출력되게된다.

 

*var 없이 변수를 선언하면 런타임시에 '전역' 변수로 선언된다.

 

명심하자. 이걸 모르면 자바스크립트 개발시 순간의 실수로 에러메세지도없고 도대체 어디가 문제인지 모르는 상황에 발생하게된다. 언어차원에서는 절대 에러가 아닌데 내가 원하는 값이 안나오게 된다는 말이다.

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

#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
jquery checkbox 제어  (0) 2015.01.02
댓글
댓글쓰기 폼