회사일이 많아 퇴근전에 글을 쓰고 있네요..ㅎㅎ 요즘 Ajax로 이런저런걸 하다보니 일이 많군요..ㅎㅎ
오늘부터는 Ajax의 프레임워크인 'PrototypeJS(이하 PJS)'를 강좌로 해볼 생각입니다. 사실 개인적인 생각으론 PJS가 프레임워크라기보단, 라이브러리에 가깝다고 생각합니다. 제가 자바개발자라서 그런지 프레임워크라고
하면 스트럿츠나,  스프링 같은 것이 먼저 떠오르기때문이죠.

위에서 나열한 자바 프레임워크들은 내부적으로 모두 MVC를 기반으로 작성되어 있으면서, 사용자로 하여금
MVC에 맞춰 개발되도록 도와줍니다. 물론 PJS도 틀을 제공하긴 하지만 MVC자체를 제공해주지는 못하고
있습니다. 나름대로 지금껏 웹개발을 해오면서 제대로된 MVC를 적용해본적은 별로 없습니다. 그나마 현재 근무하고 있는 회사에서 Ajax로 클라이언트단의 MVC를 구현하여 개발해놓게 다행이라고 해야하나? ㅎㅎ 암튼 한국 웹개발시장이 현재 그러한듯 합니다. 얼마 안되는 시간에 빠른개발을 원하다보니, 제대로 이해도 안되는
상황에서 주먹구구식으로 프레임워크에 맞춰서 개발하거나, 그도 안되는 작은 회사의 직원들은 Jsp model 1방식(jsp일때)으로 개발을 많이 하고 있습니다. "빨리빨리"의 모습이 좋은모습일 수도 있겠지만, 결코 좋은면만
가진것은 아닌것 같습니다. ㅎㅎ 이야기하다보니 또 주저리 주저리 떠들고 있군요..ㅋㅋ

오늘은 제목처럼 " PJS의 Function부분"을 진행해보자구요.
이부분은 제가 밑에 포스트한 변수범위와도 관련이 있는 부분입니다. 그 강좌를 보신 분이라면 아마도 쉽게 이해하실 수 있을거라 생각합니다.

<script>
   window.name = "the window object";

   function scopeTest(){
      alert(this.name);
   }

   scopeTest(); -------------------- ①

   var foo = {
      name : "the foo object",
      otherScopeTest : function(){
         alert(this.name);
      }
   }

   foo.otherScopeTest();------------- ②
</script>

위의 소스를 보시지요. ① 부분의 실행결과는 "the window object"가 리턴되겠죠. ② 부분의 실행결과는
"the foo object"가 되겠죠. 이해가 잘안가시는 분은 밑의 강좌를 한번 다시 읽어주세요. 계속 설명드리죠.
보시다시피 "오브젝트 안에서는 지역변수가 전역변수보다 우선한다"가 성립하는 부분입니다. 그럼 아래 코드를 봐주세요.

<script>
 var obj = {
   name : "A nice demo",
   fx : function(){
     alert(this.name);
   }
 };
 
 window.name = "I am such a beautiful window";
 
 function runFx(f){
   f();
 }

obj.fx(); ---------------------------------------- ①

 runFx(obj.fx);----------------------------------- ②

 var fx2 = obj.fx.bind(obj);
 runFx(fx2);-------------------------------------- ③
</script>


1번의 실행결과가 예상이 되나요? 그렇습니다. obj의 지역변수격인 name이 있기때문에 결과는
"A nice demo"입니다. 그러면 1번과 2번의 차이점은 무엇인가요? 네, 함수를 직접 호출해서 사용하는것과,
함수를 다른함수의 인자로넘겨 실행하는것이 다릅니다. 어떻습니까? 결과가 예상되십니까? "A nice demo"라고 답하신분이 대부분일 거라 생각합니다.. 그렇습니다.. 오답입니다 ^^; 답은 엉뚱하게도 "I am such a beautiful window"가 됩니다. 왜 이런일이 생기는 걸까요? 눈치 빠르신분은 아~! 하고 이야기 하실지도 모르겠네요.
바로 Scope의 변경때문입니다. 단순하게 obj.fx()를 실행하는 것은 오브젝트 안의 scope를 가지고 실행하기에 this.name을 찍으면 지역변수격인 "A nice demo"가  찍힙니다. 허나 두번째 방법은 좀 다릅니다.
2번의 구문을 다시 표현하면 아래와 같습니다.

function runFx(){
   alert(this.name);
}


이해가 안된다구요? 자 천천히 봅시다. runFx의 인자로 함수가 넘어갔습니다(함수를 포함한 오브젝트가
아닙니다). 그리고선 인자로 넘어온 함수는 runFx의 내부에서 실행되게 됩니다. 허나 인자로 넘어온 함수는  this.name을 찍으려고하나 runFx의 내부에는 name이란 지역변수가 존재하지 않습니다. 그래서 그 위인 전역변수중에 이름이 name 인것을 찾아 출력하려고 하고, 그결과 "I am such a beautiful window"가 출력되게 됩니다. 이해가 가셨는지요.

그럼 3번을 볼까요? 2번과는 다르게 bind라는 함수를 거쳐 runFx로 함수를 보냅니다. 결과는 ? 놀랍게도
"A nice demo"가 출력됩니다.

어째그 이런결과가 나올까요? PJS의 소스코드를 잠시 참고합니다.

Function.prototype.bind = function() {

  var __method = this, args = $A(arguments), object =  args.shift();
 
  return function() {
    return __method.apply(object,  args.concat($A(arguments)));
  }
}


PJS에는 이렇게 정의되어 있습니다.
__method에는 this가 담기는데.. 여기에선 bind 된 것이 담기므로 obj.fx가 담기게 되고,  args에는 arguments로 넘어온 obj 오브젝트가 통으로 담기게 됩니다. $A 함수는 오브젝트를 배열 오브젝트로 변경하는 역할을 담당하고 있습니다. object는 args의 shift를 담고 있는데 shift는 배열의 첫번째것을 잘라내어 담고, 나머지는
다시 자기자신에게 담는 역할을 합니다. 그러므로 처음엔 args가 arguments의 전부를 가지고 있다가 arguments의 첫번째는 object에게 주고 나머지는 다시 args에 할당됩니다. 그리고 위에서 할당된 __method를
실행하게됩니다. obj의 모든것을 넘겨받아서 내부적으로 처리하여 실행하는거죠.
소스코드보다 말이 더 어렵네요 ^^; 하핫

Function안에 있는 bindAsEventListener 또한 같은 원리입니다. 다만 Event라는 것만 다르지 다른것은
똑같습니다. 원본소스는 아래와 같습니다.

Function.prototype.bindAsEventListener = function(object) {
  var __method = this, args = $A(arguments), object = args.shift();
  return function(event) {
    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
  }
}


위의 소스설명은 하지 않겠습니다. 제가 설명한 부분을 참고하시어 직접 분석해보세요.

이상으로 PJS에 있는 Function부분을 마치겠습니다.

posted by blankus

Ajax  |  2007/06/01 22:01
이 글의 트랙백 주소 :: http://www.blankus.net/trackback/9
.
회사일이 많아 퇴근전에 글을 쓰고 있네요..ㅎㅎ 요즘 Ajax로 이런저런걸 하다보니 일이 많군요..ㅎㅎ오늘부터는 Ajax의 프레임워크인 'PrototypeJS(이하 PJS)'를 강좌로 해볼 생각입니다. 사실 개...
이름 ::   비밀번호 :: 홈페이지 :: 비밀글
등록