시간이 어떻게 될지 모르겠지만 앞으로 계속 쭉~~~~ 강좌(?)를 쓸예정이다.
참고로 혼자 떠드는 스타일이라 존칭어는 과감하게 생략토록 하겠다.ㅋㅋ
강좌라고 하기엔 좀 납득하기 어려운 부분도 있겠지만 글머리를 봐주길 바란다.
그렇다! 기초강좌다 -_-;

기초강좌의 주된 목적은 초보 또는 아직 Javascript에 대한 개념이 정립되지 않은 상태에서
이것저것 하다보니 헛깔리는 분들을 위한것이 주가 되겠다.

오늘은 첫날이므로 조금은 쉽지만 자주 헛깔릴 수 있는 것을 다뤄보겠다.
이름하여 Javascript의 Runtime이다.

말그대로 "Runtime"... (실행시간이 아니다 --;) 실행할때의 시점으로 봐주길 바란다.
주절주절 떠드는 것보다 아래의 코드를 보며 접해보는게 좋겠다 ^^*

<html>
  <script>
   function test_1(){ alert("test_1"); }
   function test_2(){ alert("test_2"); }
   function test_3(){ alert("test_3"); }

   test_1();
  </script>
  <body onload="test_2()">
   <script>test_3()</script>
  </body>
</html>

위 소스는 그리 어렵지 않다. 아니다 하나도 안어렵다. 만약 이것이 어렵다고
느끼시는 분이 있다면.... 대.략.난.감. !!

자, 해설을 해보자. 여러분들은 위의 실행순서가 어떻게 될지 예상이 되는가?
여기서 두그룹으로 나눠볼 수 있겠다.
1번째 그룹은 아마 test_1 -> test_2 -> test_3 으로 예상할 것이고,
2번째 그룹은 아마 test_1 -> test_3 -> test_2 으로 예상할 것이다.
혹시, 이 두그룹에 속하지 않는 당신이라면... 역시... 대.략.난.감 !!

직접 실행해보면 알겠지만 답은 2번째 그룹이 정답이다. 왜 이런 일이 발생할까?
쉽게 생각하면 1번째 그룹이 답이 될 수도 있다. 왜? 음.. 이제부터 그룹1을 대표해서
설명을 해주겠다 (물론 틀린해석이지만 ^^.. 가능성을 이야기해주고 싶은것이다)

test_1은 당연 먼저실행된다. 왜냐면 Javascript는 인터프리터 언어이기때문에
위에서 아래로 순차적으로 해석되어지면서 실행이 된다. 그래서 test_1이 가장먼저
실행이된다. 그리고 자주보던 onLoad 문이다..그렇다 우리는 잘배웠다!! onLoad는
body가 전부 로드되면(여기에 함정이 있다) 실행되는 것이다. 그래서 test_2가 실행되고,
body 안에 있는 test_3가 실행된다고 생각된 것이다. (사실 나도 첨엔 그리 생각했다^^;)

하지만 위에도 말했듯이 위에 말은 사실이 아니다. 더 정확하게 말하면 오해이다.
자! 그럼 사실대로 오해없이 이해해보자.

위의 잘못된 설명중 초반엔 맞는 설명이다. 어디까지냐면, onLoad전까지 이다. 그다음엔
body의 onLoad를 자세히 이해할 필요가 있다. body는 무엇인가? 그렇다. 단순한 몸뚱이가 아니다 ^^
body는 html의 몸뚱이이며 DOM객체의 일부이다. onLoad는 body, 더 정확하게는 DOM의 일부인
body가 전부 로드되었을때 실행이 되는 것이다. 그런데 왜 test_3가 먼저실행되었냐?
그건 위에 설명된 인터프리터 언어의 특성때문에 위에서 순차적으로 읽어내려가면서 실행이
되기 때문이다. 쉽게 DOM은 DOM이고 JS는 JS인것이다. 아주~ 나중에~ 다시 언급되겠지만
DOM의 참조를 JS에 넘기면 IE에서 memory leak이 발생한다. 잠시 어려운 이야기를 했는데
나중되면 다 이해하리라... 다시 본론으로 쿨럭! -_-;
body안에 스크립트가 있긴하지만 DOM의 일부가 아니기에 인터프리터의 특성으로 먼저실행되어지고,
그다음에 body onLoad가 실행되어지는 것이다. 이해하셨는가? 힘들게 설명했는데, 이해못하면 안된다 ㅠㅠ OTL

자 여기까지 이해했다면, 난이도를 조금 높여보자.

<html>
<script>

test_2();

function test_5(){
 this.msg = "hello~ test_5";
 this.call = function(){
  alert(this.msg);
 }
 test_4();
 this.call();
}

function test_1(){ alert("test_1"); }
function test_2(){ alert("test_2"); }
function test_3(){ alert("test_3"); }
function test_4(){ alert("test_4"); }

</script>

<body onload="test_1()">
<script>
 new test_5();
 test_3();
</script>
</body>
</html>

문제는 동일하다. 실행순서 실행결과를 맞추면 된다. 어려워 보이는가? 절대 그렇지 않다.
결론부터 말하자면 test_2 -> test_4 -> test_5 -> test_3 -> test_1 순이다.
이해가는 사람도 있을것이고, 아직 잘 이해가 안되는 사람도 있을 것이다. 어쩔수 없다.
이해가 안되면 되게해야 인지상종의 정신이 아니던가??

해설 들어간다.

Javascript는 인터프리터이며, 순차적으로 실행한다 했다. 근데!!!! 이게 왠말인가?
함수를 정의하기도 전에 호출을 해버린게 아닌가? 이게 말이되는건가? 결론적으로 말이된다.

Javascript는 인터프리터이므로 순차적이다. 그러나 순차적이 한줄한줄 순처적이기도 하지만, <script></script> 안에서는 한줄한줄이나, <script></script>로 봤을땐 한통속인것이다.
즉, test_2()를 먼저 호출했지만 Javascript엔진이 <script></script>한 구문을 해석하는 시간이
test_2()를 호출하는 시간하고 크게 차이 안났다는 이야기다. 아니 더 정확하게 말하자면 거의 동시에
이루어졌다고 봐야한다.
더 적나라하게 말하면 <script></script>사이에 어디에서라도 수가 정의되기전에 함수를 호출해도 동일한
태그안에서 함수가 정의만 되어있으면 호출이 된다는 이야기이다.(안될 경우있음)

어떤가? 말도 안되는 일이지 않는가? 아무리 빠르다고 해도 이게 말이되는건가? 그렇다
Javascript는 원래 말이 안되는 언어이다.. 완벽한 oop도 아니면서 oop에 가깝다.
코딩의 자율성도 상당히 높아서 잘못된(Java또는 그외 언어와 비교하여) 코딩도 맘넓게 이해해주는
센스도 있다.

여기서 잠깐! 위에 보면 test_5()를 보시라.. 좀 특이하게 생겨먹었다.
Javascript에서 "like class"(oop에서의 class와 비교하여)를 생성하는 방법중에 하나이다.
자세한건 뒤에 다루기로 한다. 여기서는 그냥 이런것도 있구나, 이렇게 쓸수 있구나하는 정도까지만
이해해 두자.

근데, 아무리 성격이 좋은 Javascript라도 안되는게 있다.

<html>
<script> test_2(); </script>
<body>
</body>
<script>
 function test_2(){ alert("test_2"); }
</script>
</html>


위 스크립트를 실행하면 어떤 결과가 나올지 예상이 되는가? 그렇다.. 에러다 -_-;;

왜 그러한가? 설명은 위에 있다. Javascript에서 엔진이 해석하는 순서는 <script></script> 단위이고,
그안에서는 대부분 자유롭게 기술할 수 있다.(안되는 경우가 있다. 언제냐고? 스스로 생각해보자 ^^)
허나 위의 구문은 하나의 <script></script>에서는 정의되지 않은 함수를 호출하고,
아래의 다른 <script></script>에서는 함수를 정의했다. 그래서 안되는거다.
Javascript의 엔진이 해석하는 단위에서 정의와 호출이 따로 있기 때문이다.

이상 Javascript 에서의 런타임에 대해서 간략하게나마 정리해 보았다.
간혹 이해가 안가시는 분이나, 도통 모르겠다고 생각되시는 분들은 차근차근 다시 위 글을 읽어 보시기
바란다. 위 내용은 어느 책에도 나와있지 않기때문에 오로지 경험에 의해서만 알 수 있는 것이다.
쉽게 "노하우"란 이야기이다. 다들 열심히 공부하여 앞으로 나올 Javascript 2.0시대에
조금이라도 쉽게 다가갈 수 있도록 화이팅이다.

posted by blankus

Javascript_base  |  2007/05/29 18:10
이 글의 트랙백 주소 :: http://www.blankus.net/trackback/2
2007/07/22 10:52 댓글에 댓글수정/삭제
안녕하세요~ Prototype 스터디 그룹의 애드 입니다.^^ 난이도가 높아진 소스에서, 결과물로 본다면 2->4->5->3->1 이 맞지만, 함수 호출 순서대로 보자면 2->5->4->3->1 이 맞겠네요~ new test_5() 하는 순간 test_5는 이미 호출이 되어버리니... 혹시라도 저같이 호출 순서와 결과에서 나타난 순서 두개로 헷갈리시는 분들이 계실꺼같아서 적어보았습니다~;;
2007/07/26 09:03 수정/삭제
그렇군요, 말을 좀 애매모호하게 적어놨네요 수정했습니다.
.
DOCHI
2007/07/25 14:49 댓글에 댓글수정/삭제
급변하는 JavaScript의 기초강좌를 써주셔서 감사합니다. ^^
잘 보았습니다.
2007/07/26 09:06 수정/삭제
자바스크립트가 급변하지는 않습니다 ^^ 다만, 우리가 모르고 있었을뿐 자바스크립트는 그렇게 계속 자리를 지키고 있습니다. ^^
열심히해서 앞으로 나올 js 2.0을 기쁘게 맞아합시다..ㅎㅎ
.
2007/11/06 20:05 댓글에 댓글수정/삭제
즉, test_2()를 먼저 호출했지만 Javascript엔진이 <script></script>한 구문을 해석하는 시간이
test_2()를 호출하는 시간하고 크게 차이 안났다는 이야기다. 아니 더 정확하게 말하자면 거의 동시에
이루어졌다고 봐야한다.
---------------------------------------------
라고 하셨지만,
그렇게는 조금 애매한듯하고요; (그럼 됐다가 안댔다가 할 수도 있잖아요^^;)
script 안에서 한번 다 읽고서 (함수내용은 말고 함수명까지만?) 다시 읽는다.. 라고 추측을 해봅니다.
적어도 동시에 읽기시작해서 함수를 호출하면 끝까지 읽어서 함수가 있는지 확인이 될 때까지 기다리기라도 하겠죠

그리고 여담이지만 제가 테스트해본 결과
함수는 호출될 때 그 내용을 읽어옵니다 (파싱)
function f (a, b) {
return a + b;
}
을 실행하는 속도 보다.
function f (a, b) {
return a + b;
return a * b;
}
을 실행하는 속도가 더 느립니다.
반복문으로 간단하게 테스트하면 알 수 있습니다.
완벽한(?) 인터프린터라면 return 을 만난이상 그 이후 내용에 대해 영향을 받지 않아야 하는 것인데, 영향을 받는 것을 보면 함수가 호출될 때 그 내용의 전체를 한번(?) 파싱(?)한다는 것을 추측해볼 수 있습니다.
이 테스트 결과로 미루어보았을 때 <script> 안에서도 함수명들을 한번 읽어내고 (내부적으로는 함수의 이름과 그 메모리 위치 정보같은 것들을 등록시키겠죠.) 인터프린팅을 시작하는 것 같습니다

ps. 그냥 단순한 저의 추측이니 틀리더라도 너무 모라하지마세요
2007/11/07 21:56 수정/삭제
네..azki님이 말씀하신 부분이 맞습니다. 저도 몇가지 방법으로 테스트를 해보았으니 정확한 논리가 서지않아 말을 얼버무리게되었습니다.ㅎㅎ
아직까지도 제가 고민하는 부분이고, 조금씩 실마리를 보이고 있으니 조만간 테스트가 끝나고.. 정확한 내용이 나오면 아마 수정이 되거나, 추가 포스팅이 되지 않을까 합니다. ^^ 이렇게 자세한 내용을 첨언해주시니.. 제 포스트를 자세히 읽어주셨다고 생각됩니다..^^ 감사하구요, 자주 들러주셔서..좋은 글 많이 남겨주세요..감사합니다.
2007/11/07 23:51 수정/삭제
제 의견을 들어주시고 같이 고민해 주시니 저도 매우 감사합니다 :]
앞으로도 좋은 내용들 많이 나눌 수 있으면 좋겠습니다
그럼 좋은 밤 되십시요 ^^;
.
이름 ::   비밀번호 :: 홈페이지 :: 비밀글
등록