블로그 이미지
초딩입맛제주아재
하고 싶은 것만 하며 살고 싶다

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
2007. 5. 22. 14:49 Programing/HTML/JavaScript/CSS
javascript의 객체의 속성은 객체.속성이름 으로  접근이 가능하다.
그리고 또 하나 다른 표현이 있는데 바로 객체['속성이름'] 이 그것이다.

var obj = new Object();
obj.id = 'first';
obj.name = 'wave';
obj.age = '20';
obj.sex = 'male';

alert(obj.id);
alert(obj['id']);

이제 객체 안을 통째로 들여다 보는 방법을 알아보자
위에서 언급한 객체['속성이름']의 표현식을 이용하면 된다.

var msg = '';

for(var temp in obj){
  msg += temp + ' = ' + obj[temp] + '\n';
}

alert(msg);

for(A in B)는 B의 속성을 하나하나 꺼내서 A에 담는다.

어찌 보면 객체 == 배열 의 형태로 보이기도 하는데, phpschool 에 이와 관련한 재밌는 토론이 있었으니 참고하길 바란다...토론보기

posted by 초딩입맛제주아재
2007. 4. 19. 17:33 Programing/JSP/ASP
기본적으로 ASP는 가변변수를 지원하지 않는다.
하지만 Execute() 를 통해서 가변변수를 구현 할 수 있다.

a = "abc"
Execute(a & "= 1")
Response.write(abc)


실행하면 1이 출력된다.

가변변수에 문자열 값을 넣을때는 이스케이프 문자 "\"를 쓴다.


Execute(a & "=" & chr(34) & "bbb" & chr(34))


불편하지만 필요하다면 쓸 수 밖에....
php는 참 편한데 :)

'Programing > JSP/ASP' 카테고리의 다른 글

웹 프린터  (0) 2007.05.23
ASP: 동적 include  (1) 2007.05.22
[펌]톰캣과 아파치,IIS연동에 관하여  (0) 2007.01.12
[ASP]php의 exit와 같은 기능을 하는 Response.end  (0) 2007.01.03
posted by 초딩입맛제주아재
2007. 4. 19. 11:43 Programing/HTML/JavaScript/CSS

아프리카 초원의 날씨만큼이나 변덕스러운 웹 세상에 또 하나의 주목할 만한 언어가 등장했다.
이름하여 Flapjax.
웬지 이름에서 AJAX의 냄세가 느껴지지 않는가?

Flapjax 홈페이지에서는 Flapjax를 다음과 같이 소개하고 있다.

Flapjax is a new programming language designed around the demands of modern, client-based Web applications. Its principal features include:

  1. Event-driven, reactive evaluation
    print time of last click of btn1 or btn2 time: {! merge($EVENT('btn1', 'click'), $EVENT('btn2', 'click')).
    snapshot((new Date()).getTime()) !}
  2. Persistent data saved on a data store we provide
    keep a copy on the server of 'age' as it changes writePersistentObject($E('age'), {path: ['savedAge']});
  3. Convenient data sharing
    create a link to share the current user's tasklist getSharingConsoleLink('receivepage.html?user=' + uidB, ['tasklist']);
  4. Access-control for shared data
    display whether the user can write to an object {! readPermissionsB({path:['tasklist']}).has('WRITE')?'yes':'no'!}
  5. Interfaces to external Web services
    show the first link of a user's delicious bookmarks <input type=text id=u value='enter name'/>:
    {! getWebServiceObject_e({url: 'del.icio.us/feeds/json/'
    + $B('u'), serviceType: 'jsonLiteral'}).posts[0].d !}
  6. Optional templating syntax
    provide a live preview of a form value <input type=text id=age/>
    preview: {! 'age:' + $B('age') !}

홈페이지에서는 Flapjax 를 새로운 언어로 규정하고 있는데 실제로 Flapjax 코드를 보면 전혀 낯설지가 않다.
그 이뉴는 Flapjax가 Javascript를 확장한 것이기 때문인데 다음 예제를 보면 무슨말인지 이해가 갈 것이다.

<html>
  <head>
  <script lang="text/javascript" src="/demos/flapjax.js">
  </script>
  <script lang="text/javascript">
     var loader = [];
     var flapjax = flapjaxInit(false, false);
  </script>
  <title>
     Flapjax Demo: Where's the Mouse?: Flapjax Scripting
  </title>
 
  <script lang="text/javascript" type="">
     function loader0()
     {flapjax.insertDomB(flapjax.mouseTop_b(document), "Mtop");
      flapjax.insertDomB(flapjax.mouseLeft_b(document), "Mleft");}
     loader.push(loader0);
  </script>
 
  </head>
 
  <body onload="flapjax.forEach(function(l){ l(); }, loader)">
  <p>
     The mouse's coordinates are
&lt;
     <span id="Mleft">
       _
     </span>
     ,
 
     <span id="Mtop">
       _
     </span>
     &gt;.

  </p>
 
  </body>
 
</html>

위 예제는 마우스 포인터의 위치를 화면에 표시해주는 코드이다.
기존의 Javascript 코드와 전혀 다를바가 없다.

하지만, 사실 이 코드는 컴파일된 코드이다.
갑자기 무슨 컴파일이 나오는지 당황하겠지만 Flapjax는 Flapjax API를 이용해 코드를 작성하고  컴파일러를 통해서 아웃풋을 만들어야 브라우져에서 인식할 수 있다.
위 코드의 실제 Flapjax 코드는 아래와 같다.

<html>
<head>
<title>Flapjax Demo: Where's the Mouse?: Flapjax Scripting</title>

<script lang="flapjax">
insertDomB(mouseTop_b(document), 'Mtop');
insertDomB(mouseLeft_b(document), 'Mleft');
</script>

</head>

<body>
<p>
The mouse's coordinates are
&lt;<span id="Mleft">_</span>,
  <span id="Mtop">_</span>&gt;.
</p>
</body>

</html>


이처럼 Flapjax를 이용하면 개발자가 작성할 코드가 줄어들게 되는데 Flapjax측은 그 양을 아웃풋의 두배정도까지 줄일 수 있다고 한다.

단순히 코드의 양을 줄이는것이 Flapjax의 전부라면 Flapjax에 의미를 둘 수는 없다.
Cameron Laird은 IBM 개발자 네트워크에 포스팅한 Flapjax 튜토리얼에서 Flapjax를 특징을 아래와 같이 설명하고 있다.

Flapjax를 배워야 하는 이유

Flapjax는 Ajax를 손쉽게 코딩할 수 있는 방법을 제공하지만 Ajax를 편리하게 쓸 수 있는 래퍼 그 이상이다. 다음 섹션에서는 Flapjax에 대해 좀더 자세히 다루고자 한다. Flapjax에 대한 전체 내용을 다루기에는 본 튜토리얼의 목적에 벗어나는 감이 있어 일부만 소개한다. 본 기술문서에서는 다음 내용을 비롯하여 Ajax 프로그래밍 기술을 단순화하는 데 Flapjax가 어떤 역할을 담당하는지 보여준다.

  • 브라우저의 "새로 고침" 업데이트 관리
  • 사용자의 포인트 앤 클릭에 대한 응답
  • 복잡한 웹 애플리케이션을 위한 네트워크 로드 최적화
  • "외부" 서버 정보 검색

Flapjax는 입력(예: 최종 사용자의 동작과 선택)과 출력(예: 브라우저 창에서 보기) 간의 원활한 정보 교환, 즉 "반응"을 정의하고 표현하는 데 사용된다. 동시에 Flapjax는 기존 자바스크립트 작업과 호환 가능하다. Flapjax에는 자바스크립트에서 이미 쓰이고 있는 DHTML(Dynamic HTML)과 CSS(Cascading Style Sheets)가 사용되며, 현재 어떠한 새로운 시각적 요소도 추가되지 않았다. 이러한 관점에서 Flapjax는 순수하게 알고리즘 방식을 사용하고 "시각적"인 어떠한 것도 제공하지 않으며 이미 알고 있는 위젯을 더 쉽게 프로그래밍할 수 있도록 도와준다.


갈수록 AJAX 애플리케이션의 개발이 활발하게 이루어지고 있다.
더이상 AJAX는 고급 기술자들만의 전유물이 아니다.
다양한 프레임워크와 손쉽게 원하는 아웃풋을 만들어주는 언어와 툴들이 하루가 멀다하고 발표되고 있다.
Flapjax도 그 중 하나로, 앞으로 얼마만큼 개발자들의 호응을 얻으며 발전해 나갈지는 미지수다.
하지만 분명한것은 Flapjax는 배우기 어려운 언어도 아니며 사용하기 까다로운 언어도 아니라는 것이다.
그리고 그점은 분명 메리트로서 작용할 것이다.


posted by 초딩입맛제주아재
2007. 4. 18. 15:08 Programing/HTML/JavaScript/CSS
이 포스팅에서 '탭'이라함은 파이어폭스나 IE7에서 쓰이는 탭브라우징의 그 '탭'과 같은 의미이다.
다음 그림을 보면 쉽게 이해가 갈 것이다.

탭이란

Ariticles,Location log,Key Log 같은 것들이

컨텐츠가 표시되는 영역은 모든 탭이 똑 같다.
여러 컨턴츠 레이어들이 겹쳐져 있는 상태에서 선택된 탭에 해당하는 컨텐츠만 사용자에게 보여주는 것이다.

보통 이 탭기능을 웹에 표현하는 방법으로 이미지를 주로 쓴다.
이미지로 표현하는것이 미관상 좋고 만들기도 수월하기 때문인데, CSS 와 javascript 로 구현하는것도 가능하다.
심플한 텍스트 기반 페이지에 탭기능을 추가하고 싶다면 주목!

다음과 같은 탭을 만들어 보겠다.
오늘 이걸 하느라 아침 시간을 다 보냈다....내공부족...
사용자 삽입 이미지

tab1 ~ tab3 까지 총 세개의 탭은 각각 content1 ~ content3 까지 자기만의 컨텐츠를 갖고 있다.
tab을 누르면 활성화된 탭과 컨텐츠 레이어는 배경색이 흰색으로 바뀌고 활성상태에서 비활성 상태로 전환되는 탭은 배경색이 회색으로 바뀐다.

코드를 살펴보도록 하겠다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> Switching Tab </title>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<script type="text/javascript">
<!--
var model = new Array();

function init(){
}
-->
</script>
<style>
.tab{
   width: 50px;
   height: 20px;
   border-top: solid 1px #D9D9D9;
   border-right: solid 1px #D9D9D9;
   border-left: solid 1px #D9D9D9;
   background-color: #EEEEEE;
   position: absolute;
   z-index: 2;
}

#tab1{
   margin-left: 10px;
}

#tab2{
   margin-left: 60px;
}

#tab3{
   margin-left: 110px;
}

.content{
   width: 200px;
   height: 50px;
   border: solid 1px #D9D9D9;
   background-color: #EEEEEE;
   position: absolute;
   top: 19px;
   z-index: 1;
}

#layer1{
   top: 50px;
   left: 50px;
   position: absolute;
}

#layer2{
   top: 50px;
   left: 50px;
   position: absolute;
}

#layer3{
   top: 50px;
   left: 50px;
   position: absolute;
</style>
</head>

<body onload="init()">

<div id="layer1">
   <div id="tab1" class="tab">tab1</div>
   <div class="content">content 1</div>
</div>

<div id="layer2">
   <div id="tab2" class="tab">tab2</div>
   <div class="content">content 2</div>
</div>

<div id="layer3">
   <div id="tab3" class="tab">tab3</div>
   <div class="content">content 3</div>
</div>

</body>
</html>

model은 레이어의 레퍼런스를 담을 배열 객체이다.
매번 각 레이어 객체를 찾아야 하는 불편을 덜기 위해 사용했다.

이제 본격적으로 javascript를 구현해보자.
onload 시에 호출 되는 init() 함수와 그에 따른 몇개의 함수가 필요하다.

function init(){
   var layer1 = document.getElementById('layer1');
   var layer2 = document.getElementById('layer2');
   var layer3 = document.getElementById('layer3');

   model.push(layer1);
   model.push(layer2);
   model.push(layer3);

   for(var i=0,max=model.length; i<max; i++){
       set_event_listener(model[i],'mouseover','switching_tab');
   }

   switch_execute(layer1);
}
init()함수는 각 레이어의 레퍼런스를 배열 model 에 추가하고 이벤트를 걸어준 다음 첫번째 레이어를 활성화 시킨다.


function set_event_listener(obj,evt_type,callback){
   if(window.event){
       obj.attachEvent('on' + evt_type,eval(callback));
   }else{
       obj.addEventListener(evt_type,eval(callback),false);
   }
}
set_event_listener() 함수는 주어진 객체에 evt_type 형식의 이벤트를 걸어준다.


function switching_tab(e){
   var target;

   if(window.event){
       target = window.event.srcElement;
   }else{
       target = e.target;
   }

   switch_execute(target.parentNode);
}
switching_tab() 함수는 이벤트가 발생할때 호출 되며 이벤트가 일어난 객체를 switch_execute 로 보내는 역할을 한다.



function switch_execute(layer){
   var visible_tab_top = -1;
   var hidden_tab_top = 0;

   if(window.navigator.appName.indexOf('Explorer') > -1){
       visible_tab_top++;
       hidden_tab_top++;
   }


   for(var i=0,max=model.length; i<max; i++){
       var tab = get_tab_element(model[i]);
       var content = get_content_element(model[i]);

       if(model[i] == layer){
           model[i].style.zIndex = 99;
           tab.style.top = visible_tab_top;
           tab.style.backgroundColor = '#FFFFFF';
           content.style.backgroundColor = '#FFFFFF';
       }else{
           model[i].style.zIndex = 0;
           tab.style.top = hidden_tab_top;
           tab.style.backgroundColor = '#EEEEEE';
           content.style.backgroundColor = '#EEEEEE';
       }
   }
}
switch_execute() 함수는 주어진 레이어를 활성화 시키고 나머지 레이어를 비활성화 시키는 일을 한다.
visible_tab_top과 hidden_tab_top 값을 브라우져에 따라 달리한 이유는 IE와 Mozila 계열의 렌더링 방식의 차이때문이다.
기본값은 FF를 위한 값이다.
만약 위와 같은 처리를 생략했을 경우 IE에서 는 활성화 된 탭과 그에 해당하는 컨텐츠 레이어 사이의 경계선이 그대로 남게 되고 FF에서는 탭의 좌우 경계선이 컨텐츠 레이어 안으로 비집고 들어오는 모습을 보게 될 것이다.


function get_tab_element(model){
   var child = model.childNodes;

   for(var i=0,max=child.length; i<max; i++){
       if(child[i].nodeType == 1 && child[i].className == 'tab'){
           return child[i];
       }
   }
}

function get_content_element(model){
   var child = model.childNodes;

   for(var i=0,max=child.length; i<max; i++){
       if(child[i].nodeType == 1 && child[i].className == 'content'){
           return child[i];
       }
   }
}
위 두 함수는 레이어에서 탭과 컨텐츠 영역을 추출하는 용도로 쓰인다.
역시 IE와 FF의 차이가 있기 때문에 firstChild, lastChild 를 쓰지 않았다.
속도가 느려지는 일이 발생한다면 위 두함수를 하나로 묶어서 반복문을 하나로 축약해야 할 것이다.
별로 그럴일은 없을것 같지만...

posted by 초딩입맛제주아재
2007. 4. 6. 13:59 Programing/HTML/JavaScript/CSS
자바스크립트는 참 어렵다.
쉬운것 같으면서도 어렵다.
그 이유가 바로 이 글에 나와있다.

===================================================================================

JavaScript는 LiveScript라고 불렸어야 되지 않았나 생각됩니다.
  JavaScript는 Java와는 아무 관계가 없으며,
  Sun의 공동설립자 중 한명인 Bill Joy는 Netscape가 JavaScript라는
  이름을 사용할 수 있도록 허용한 것을 후회한다고 밝힌적이 있습니다.- onjo
http://www.zdnet.co.kr/news/internet/etc/0,39031281,39149821,00.htm
http://www.elancer.co.kr/eTimes/page/eTimes_view.html?str=c2VsdW5vPTQ5ODQ=

자바스크립트 추천서적
  JavaScript: The Definitive Guide, David Flanagan, O'REILLY

--------------

원저 : <JavaScript: The World's Most Misunderstood Programming Language>
http://javascript.crockford.com/javascript.html

번역 : <JavaScript: 세상에서 가장 오해가 많은 프로그래밍 언어>
http://home.postech.ac.kr/%7Eskyul/javascript.html

번역자 : 서광열 http://skyul.tistory.com/172


JavaScript:
세상에서 가장 오해가 많은 프로그래밍 언어

Douglas Crockford
www.crockford.com

번역: Kwang Yul Seo
skyul.tistory.com

Mocha, LiveScript, JScript, ECMAScript 등으로도 불리는 JavaScript는 세상에서 가장 유명한 프로그래밍 언어 중에 하나입니다. 사실상 세상의 모든 개인 컴퓨터에 최소한 하나 이상의 JavaScript 인터프리터가 설치되어 있고 활발하게 사용되고 있습니다. 이러한 JavaScript는 인지도는 전적으로 월드와이드웹(WWW)의 스크립트 언어라는 역할 덕택입니다.

이런 인지도에도 불구하고, JavaScript가 매우 동적이며 객체지향의 범용 프로그래밍 언어라는 사실을 아는 이는 드뭅니다. 이런 사실이 어떻게 비밀이 될 수 있었을까요? 왜 이 프로그래밍 언어는 잘못 이해된 것일까요?
이름

Java- 접두사를 보면 JavaScript가 Java와 어떤 식으로는 연관 관계가 있을 것처럼 보입니다. 즉, JavaScript는 Java의 서브셋이거나 기능이 부족한 버전의 Java라는 인상을 줍니다. 이 이름은 혼란을 주기 위해 의도적으로 지어진 것으로 보이는데, 이런 오해가 혼란을 야기했습니다. JavaScript는 인터프리트되는 자바가 아닙니다. 자바 자체가 인터프리트되는 언어입니다. JavaScript는 Java와는 다른 언어입니다.

Java가 C와 문법적으로 유사하듯이 JavaScript는 Java와 유사합니다. 하지만 Java가 C의 서브셋이 아닌 것처럼 JavaScript도 Java의 서브셋이 아닙니다. JavaScript는 Java(초기의 Oak)과 원래 의도했던 응용 프로그램 부분에서는 Java보다 더 뛰어납니다.

JavaScript는 Java의 고향인 썬마이크로시스템즈(Sun Microsystems)에서 개발된 것이 아닙니다. JavaScript는 네스케이프(Netscape)에서 개발되었습니다. 원래는 LiveScript라고 불렸는데, 이 이름은 그다지 혼란스럽지 않았지요.

-Script 접미사는 JavaScript가 실제 프로그래밍 언어가 아니라 프로그래밍 언어보다 약한 스크립트 언어라는 인상을 줍니다. 하지만 이는 전문화의 문제입니다. C 언어와 비교해 보면, JavaScript는 표현력과 역동성(dynamism)을 위해 성능을 희생한 것입니다.
C 언어의 옷을 입은 Lisp

JavaScript의 C 언어 같은 문법(중괄호와 투박한 for 문을 포함)은 JavaScript가 일반적인 프로시저형 언어로 보이게 합니다. 이는 잘못된 오해인데, 왜냐하면 JavaScript는 C나 Java보다는 Lisp or Scheme와 같은 함수형 언어와 더 유사점이 많기 때문입니다. JavaScript는 리스트 대신에 배열이 있고, 속성 리스트(역주: 일종의 해시테이블) 대신에 오브젝트가 있습니다. 함수가 제1클래스이고, 클로저도 있습니다. 또한 괄호를 맞출 필요 없이 람다(lamda, 익명 함수)를 사용할 수도 있습니다.
고정역할

JavaScript는 네스케이프 네비게이터에서 동작하도록 설계되었습니다. 네스케이프에서의 성공은 JavaScript가 거의 모든 웹브라우저에서 표준 장치가 되도록 만들었습니다. 이는 JavaSciript가 웹 개발언어라는 이미지를 고정해 버렸습니다. JavaScript는 프로그래밍 언어계의 죠지 리브스(George Reeves), 슈퍼맨을 연기한 배우가 되었습니다. 하지만 JavaScript는 웹과 관련되지 않은 대규모의 응용 프로그램 개발에도 잘 어울리는 언어입니다.
움직이는 목표물

JavaScript는 첫 번째 버전은 매우 빈약했습니다. 예외 처리, 내부 함수, 상속 등의 기능이 없었습니다. 현재의 JavaScript는 완전한 객체지향 프로그래밍 언어입니다. 하지만 언어에 대한 여러 의견들은 여전히 예전의 성숙하지 못한 모습에 바탕을 두고 있습니다.

JavaScript 언어에 대한 관리 책임을 맡고 있는 ECMA 위원회는 비록 그 의도는 좋지만 이미 너무 많은 버전이 존재한다는 JavaScript의 가장 큰 문제점을 악화시키는 확장 작업을 하고 있습니다.
설계 오류

완벽한 프로그래밍 언어는 없습니다. JavaScript도 설계 오류를 포함하고 있습니다. + 를 자동 타입 변환과 함께 더하기와 문자열 병합이라는 두 가지 의미로 오버로딩한 것, 실수를 저지르기 쉬워서 사용을 피해야 하는 with 문 등이 여기에 해당합니다. 예약어 정책도 너무 까다롭습니다. 정규 표현식 기술 방법과 세미콜론 삽입은 아주 큰 실수입니다. 이런 실수는 프로그래밍 오류를 야기하고, 언어 설계 자체를 의문스럽게 만들게 됩니다. 다행히도, 이런 문제의 상당수는 lint라는 좋은 프로그램으로 완화가 가능합니다.

전체적인 언어 설계는 매우 안전합니다. 놀랍게도, ECMAScript 위원회는 이런 문제를 수정하는데 별로 관심이 없는 것처럼 보입니다. 아마도 그들은 새로운 것을 만드는데 더 관심이 많은 것 같습니다.
잘못된 구현들

JavaScript 초기 구현의 일부는 매우 버그가 많습니다. 이는 언어에 나쁜 영향을 미치고 있습니다. 설상가상으로 이런 구현들이 끔찍히도 버그가 많은 브라우저에 내장되어 있었습니다.
안 좋은 책들

사실상 JavaScript에 관한 거의 모든 책이 엉망입니다. 이 책들은 오류와 나쁜 예제투성이고, 잘못된 방법을 부추깁니다. 언어의 중요한 기능들이 잘못 설명되거나 아에 빠져있는 경우도 흔합니다. 필자는 십여 권의 JavaScript 책을 검토해보았는데, 다음 단 한 권의 책만 추천합니다. JavaScript: The Definitive Guide (5th Edition) by David Flanagan. (필자들에게: 좋은 책을 쓰셨다면 검토본을 보내주세요.)
불충분한 표준

언어의 공식 명세서는 ECMA가 작성하였습니다. 이 명세서는 품질이 매우 나쁩니다. 읽기도 어렵거니와 이해하기는 훨씬 어렵습니다. 이 제대된 책이 없는 문제와도 연결되는데, 저자들이 언어에 대한 그들의 이해를 높이기 위해 표준 문서를 활용할 수 없기 때문입니다. ECMA와 TC39 위원회는 깊이 반성해야 할 것입니다.
초보자들

JavaScript를 작성하는 대부분의 사람들은 개발자가 아닙니다. 그들은 좋은 프로그램을 쓰는 훈련을 받지 못했고 원칙이 부족합니다. JavaScript는 뛰어난 표현력을 가졌기에 그들은 어쨌건 유용한 프로그램을 작성할 수 있습니다. 이는 JavaScript는 단지 초보자들을 위한 것이지 전문가 용은 아니라는 인상을 주었습니다. 이는 사실이 아닙니다.
객체지향

JavaScript는 객체지향일까요? JavaScript는 데이터와 데이터를 처리할 수 있는 메서드를 담을 수 있는 오브젝트를 제공합니다. 오브젝트는 다른 오브젝트를 저장할 수도 있습니다. 클래스는 없지만, 클래스 변수와 메서드를 담을 수 있는 클래스 역할을 하는 생성자가 있습니다. 클래스 기반의 상속 기능은 없지만, 프로토타입 기반의 상속 기능을 제공합니다.

오브젝트 시스템을 만드는 두 가지 주요 방법은 상속(is-a)과 집합(has-a)이 있습니다. JavaScript는 두 가지 방법을 다 지원하지만, 언어의 동적인 속성은 집합(aggregation)일 때 더 빛을 발합니다.

일부에서는 JavaScript가 정보 은닉을 제공하지 않기 때문에 참된 의미의 객체지향이 아니라고 말합니다. 이는 오브젝트에 private 멤버와 메서드가 없다는 뜻입니다. 모든 멤버는 public입니다.

하지만 JavaScript 오브젝트는 private 변수와 private 메소드를 가질 수 있다.로 밝혀졌습니다. 물론, JavaScript는 세상에서 가장 오해가 많은 언어이기에 이를 이해하는 사람은 많지 않습니다.

또한 일부는 JavaScript가 상속을 지원하지 않기 때문에 진정한 의미의 객체 지향 언어라고 말합니다. 하지만 JavaScript는 전통적인 상속 방식뿐만 아니라 다른 코드 재활용 패턴 또한 제공한다. 라는 사실이 밝혀졌습니다.


[참조문서]

Copyright 2001 Douglas Crockford. All Rights Reserved Wrrrldwide.
JavaScript:
The World's Most Misunderstood Programming Language

Douglas Crockford
www.crockford.com

JavaScript, aka Mocha, aka LiveScript, aka JScript, aka ECMAScript, is one of the world's most popular programming languages. Virtually every personal computer in the world has at least one JavaScript interpreter installed on it and in active use. JavaScript's popularity is due entirely to its role as the scripting language of the WWW.

Despite its popularity, few know that JavaScript is a very nice dynamic object-oriented general-purpose programming language. How can this be a secret? Why is this language so misunderstood?
The Name

The Java- prefix suggests that JavaScript is somehow related to Java, that it is a subset or less capable version of Java. It seems that the name was intentionally selected to create confusion, and from confusion comes misunderstanding. JavaScript is not interpreted Java. Java is interpreted Java. JavaScript is a different language.

JavaScript has a syntactic similarity to Java, much as Java has to C. But it is no more a subset of Java than Java is a subset of C. It is better than Java in the applications that Java (fka Oak) was originally intended for.

JavaScript was not developed at Sun Microsystems, the home of Java. JavaScript was developed at Netscape. It was originally called LiveScript, but that name wasn't confusing enough.

The -Script suffix suggests that it is not a real programming language, that a scripting language is less than a programming language. But it is really a matter of specialization. Compared to C, JavaScript trades performance for expressive power and dynamism.
Lisp in C's Clothing

JavaScript's C-like syntax, including curly braces and the clunky for statement, makes it appear to be an ordinary procedural language. This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. It has arrays instead of lists and objects instead of property lists. Functions are first class. It has closures. You get lambdas without having to balance all those parens.
Typecasting

JavaScript was designed to run in Netscape Navigator. Its success there led to it becoming standard equipment in virtually all web browsers. This has resulted in typecasting. JavaScript is the George Reeves of programming languages. JavaScript is well suited to a large class of non-Web-related applications
Moving Target

The first versions of JavaScript were quite weak. They lacked exception handling, inner functions, and inheritance. In its present form, it is now a complete object-oriented programming language. But many opinions of the language are based on its immature forms.

The ECMA committee that has stewardship over the language is developing extensions which, while well intentioned, will aggravate one of the language's biggest problems: There are already too many versions. This creates confusion.
Design Errors

No programming language is perfect. JavaScript has its share of design errors, such as the overloading of + to mean both addition and concatenation with type coercion, and the error-prone with statement should be avoided. The reserved word policies are much too strict. Semicolon insertion was a huge mistake, as was the notation for literal regular expressions. These mistakes have led to programming errors, and called the design of the language as a whole into question. Fortunately, many of these problems can be mitigated with a good lint program.

The design of the language on the whole is quite sound. Surprisingly, the ECMAScript committee does not appear to be interested in correcting these problems. Perhaps they are more interested in making new ones.
Lousy Implementations

Some of the earlier implementations of JavaScript were quite buggy. This reflected badly on the language. Compounding that, those implementations were embedded in horribly buggy web browsers.
Bad Books

Nearly all of the books about JavaScript are quite awful. They contain errors, poor examples, and promote bad practices. Important features of the language are often explained poorly, or left out entirely. I have reviewed dozens of JavaScript books, and I can only recommend one: JavaScript: The Definitive Guide (5th Edition) by David Flanagan. (Attention authors: If you have written a good one, please send me a review copy.)
Substandard Standard

The official specification for the language is published by ECMA. The specification is of extremely poor quality. It is difficult to read and very difficult to understand. This has been a contributor to the Bad Book problem because authors have been unable to use the standard document to improve their own understanding of the language. ECMA and the TC39 committee should be deeply embarrassed.
Amateurs

Most of the people writing in JavaScript are not programmers. They lack the training and discipline to write good programs. JavaScript has so much expressive power that they are able to do useful things in it, anyway. This has given JavaScript a reputation of being strictly for the amateurs, that it is not suitable for professional programming. This is simply not the case.
Object-Oriented

Is JavaScript object-oriented? It has objects which can contain data and methods that act upon that data. Objects can contain other objects. It does not have classes, but it does have constructors which do what classes do, including acting as containers for class variables and methods. It does not have class-oriented inheritance, but it does have prototype-oriented inheritance.

The two main ways of building up object systems are by inheritance (is-a) and by aggregation (has-a). JavaScript does both, but its dynamic nature allows it to excel at aggregation.

Some argue that JavaScript is not truly object oriented because it does not provide information hiding. That is, objects cannot have private variables and private methods: All members are public.

But it turns out that JavaScript objects can have private variables and private methods. (Click here now to find out how.) Of course, few understand this because JavaScript is the world's most misunderstood programming language.

Some argue that JavaScript is not truly object oriented because it does not provide inheritance. But it turns out that JavaScript supports not only classical inheritance, but other code reuse patterns as well.

Copyright 2001 Douglas Crockford. All Rights Reserved Wrrrldwide.

'Programing > HTML/JavaScript/CSS' 카테고리의 다른 글

What is the Flapjax.  (0) 2007.04.19
Switching Tab  (1) 2007.04.18
Javascript 의 Object : new Object() ?===? {}  (0) 2007.04.06
AJAX 실전 #2 - 주소록 구현 준비  (1) 2007.03.30
Array.remove()  (3) 2007.03.28
posted by 초딩입맛제주아재
2007. 4. 6. 11:01 Programing/HTML/JavaScript/CSS
스쿨에 javascript 의 색다른 표현식에 관한 글이 올라왔다(by 행복한고니)

그중 new Object === {} 라는 고니님의 의견에 숨어지내리님이 급 제동을 걸어왔다.
너무나도 살벌한 분위기 속에서 결국 두 분의 논쟁에는 결론이 나질 않았고
나는 개인적으로 무소레즈님의 코멘트를 이 논쟁의 결론으로 치부한다.


무소레즈님의 댓글


---------------------------------------
1. new Object() === {} 가 같다?
2. Object 가 {} 으로 만들어진다?
3. constructor 의 비교로 객체가 똑같다고 말할수 있다?
4. Object 는 Function 의 instance 이다?
---------------------------------------

1. new Object() === {} 가 같다?
답변 1. 엄밀하게 다릅니다.

    ( new Object() === {} )  의 결과는 false 입니다.
    하지만 함수 객체타입은 같기에  instance 를 비교하면 true 입니다.
    왜냐하면 같은 Object 함수의 객체타입으로 생성되기 때문입니다.
    어떤 함수든 new 통하여 새로운 instance 개체를 생성하면
    어떤 instance 개체든 Object 함수 객체타입의 instance 를 갖습니다.

    예를 들어

        today = new Date();

        today 라는 instance 개체는
        Date 함수객체타입의 instance 이기도 하지만
        Object 함수 객체타입의 instance 이기도 합니다.

    또한 사용자 정의 함수를 통하여 새로운 instance 개체를 생성해도 마찬가지입니다.

        function funcName() {
        }
        fn = new funcName();

        fn 이라는 instance 개체는
        funcName 함수객체타입의 instance 이기도 하지만
        Object 함수 객체타입의 instance 이기도 합니다.

        fn 은 독립적인 instance 개체로서
        funcName 이라는 함수객체에서 정의된 구조(초기환경설정)의 instance 을 가졌다는 것이지요.

        만약 funcName 함수로 또다른 instance 개체를 생성한다면

        fn2 = new funcName();

        fn2 은 fn 과는 서로다른  instance 개체이지만
        funcName 이라는 함수명으로 정의된 구조를 가진 같은 instance 를 가집니다.
        fn1 과 fn2 는 같은 instance 를 가지고 있지만 서로 다른 개체입니다.


    (new Object) 와  {} 에의해 생성된 각각의 instance 객체변수로 비교하자면

        x1=new Object
        x2=new Object
        y1={};
        y2={};

        (x1 === x2);
        (y1 === y2)
        (x1 === y1);
        (x2 === y2);

    모두 false 입니다.  생성된 instance 개체가 서로 독립적이기 때문이지요.
    하지만  instanceof 연산자를 이용하여 비교해보면 모두 같은 instance 를 가지고 있습니다.

    Object 함수객체 타입은  ( Object.prototype.constructor ) 로 알아낼수 있습니다.
      결과는 :  function Object() { [native code] }
    funcName 함수객체 타입은  ( funcName.prototype.constructor ) 로 알아낼수 있습니다.
      결과는 : function funcName() { }

    (new Object ) 와 {} 는 미리 정의된 Object 함수 객체를 통하여
    서로다른 새로운 instance 개체들을 생성합니다.
    사용자 정의 함수에서 처럼  funcName 이 없기때문에
    Object 함수 객체타입의 instance 만을 갖게 되는 것입니다.

    ★ 그렇다고 (new Object) 와 {} 가 Object 함수객체 내부에서 주어진 정의가 완전히 같은가?
    그렇지 않습니다.
    {} 는 Object initializer (개체 초기화 지정자) 라고 불리우며,
    Object initializer 라 불리우는 {} 를 다른 함수의 내부에서 사용시
    Object initializer 를 호출할때 마다, {} 에의 정의된  속성과 그에 할당된 표현식이나 값을
    매번 다시 해석(interpret) 한다는 것이 (new Object) 와 다릅니다.

    함수내부에서 개체 초기화 지정자인 {} 를 정의하고
    그 함수를  호출하면 {} 에의해 정의된 속성과 그 값을 다시 해석하여
    매번 초기화 시킨다는것입니다.

        function funcName (cond) {
                A=3;
                B={ A:5 };
                C=new Object;
                Object.prototype.A=7;

                if(cond==1) return B.A;
                else if( cond==2) return C.A;
                else  return A;
        }

        A1=funcName(0);
        B1=funcName(1);
        C1=funcName(2);

        A2=funcName(0);
        B2=funcName(1);
        C2=funcName(2);


        A1 과 A2 는 메모리에 이미 저장된 "3" 이란 값을 반환 받습니다.
        C1 과 C2 도 메모리에 이미 저장된 "7" 이란 값을 반환 받습니다.
        B1 과 B2 는 각각 호출시 초기화 지정자를 재 해석하여 메모리에 다시 올려 놓고,
        그 후에 "5" 라는 값을 반환합니다.

        B 는  초기화 지정자 {}로 할당 받았기 때문에
        매번 함수를 호출 할때마다  B 의 속성과 값을 재 해석하여 메모리에 재 저장합니다.
        즉, 함수를 호출할때마다 매번 다시 초기화 시킨다는 말입니다.


        만약 함수 외부에서 초기화 지정자를 사용했다면
        var G={ A: 9 };
        G.A 를 호출할때 이미 초기화되어 메모리에 저장되어 있는 "9" 라는 값을 불러오게 됩니다.
        다른 곳에서 G.A 를 호출해도 역시 이미 저장되어 있는 값 "9"를 반환합니다.
        함수 내부에서 처럼 재 해석하여 재 초기화 시키는 것이 아닙니다.

        C1 과 C2 를 호출하면 이미 메모리에 저정되어 있는  "7" 이라는 값을 반환합니다.
        B1 과 B2 처럼 호출할때마다 재 초기화 시키는 것이 아닙니다.

        그렇게 (new Object ) 와 {} 는 다릅니다.


2. Object 가 {} 으로 만들어진다?
답변 2.
    {} 를 호출하면 내부에서 새로운 (new Object) 를 생성하여 instance 개체를 반환한다고 알고 있습니다.


3. constructor 의 비교로 객체가 똑같다고 말할수 있다?
답변 3.
    (객체.constructor) 의 사용은 생성자가 어떤 객체타입을 가지고 있는지 참조할수 있도록
    미리 정의되어 있는 Object 의 prototype 일뿐입니다.
    프로그램의 처리 로직에따라 객체의 속성으로써 prototype 정의는 언제든 변경 가능하며
    변경된 결과를 처리 조건에따라 필요할때 마다 활용할 수 있습니다.

    (개체.constructor) 는 
    개체를 새로 생성했을때 그 개체가
    어떤 객체 타입을 가진 생성자 함수로부터 생성된 개체인지를 참조할 수 있도록
    Javascript 에서 미리 정의해둔 하나의 속성 일뿐입니다.
    변경 불가한 상수가 아니란 것이지요.
    프로그램 처리의 상황에따라 그 값을 변경하며, 참조하여 활용할 수 있습니다.

    "constructor 의 비교로 객체가 똑같다고 말할수 있습니다."
    에대해서는 그럴수도 있고 아닐수도 있겠지요.
    프로그램의 처리 상황에따라 그 속성을 주어진대로 활용하거나, 변경하여 사용하거나
    아니면 사용하지 않거나..
    엿을 파는 엿장수 맘 아니겠습니까?

    엿장수 맘대로 사용했을때 문제가 발생할 여지가 있다면야 그렇게 사용해서는 안되겠지요.
    어느 분이든...  어떤 경우에 문제가 생기는지 알려주시면
    저도 다음부터는 유의하여 사용해 보겠습니다.


4. Object 는 Function 의 instance 이다?
답변 4.
    이미 정의되어 있는 Object 는 Function 함수 객체로부터 생성된 함수 객체이기때문에
        Function 함수 객체타입의 instance 를 갖습니다.
        또한 동시에 new 를 통하여 생성되기때문에 Object 객체타입의 instance  를 갖기도 합니다.


posted by 초딩입맛제주아재
2007. 3. 30. 14:33 Programing/HTML/JavaScript/CSS

이번 시간에는 주소록의 뼈대를 만들것이다.
간단한 DB 테이블을 하나 만들고, PHP를 이용해서 DB작업을 위한 서버프로그램을 만들것이다.
그리고 다음장에서 주소록의 핵심인 주소록의 데이터를 사용자가 입력/수정/삭제 할 수 있는 HTML페이지를 작성하도록 하겠다.

DB

주소록은 간단하게 만들기로 하였다.
이름,연락처,주소 그리고 인덱스.
총 4개의 필드만 필요하다. 뭐 더 만들고 싶은 필드가 있으면 그건 각자 알아서...

CREATE TABLE addressbook (
  idx INT NOT NULL AUTO_INCREMENT ,
  name VARCHAR( 30 ) NOT NULL ,
  tel VARCHAR( 30 ) NOT NULL ,
  addr VARCHAR( 100 ) ,
  PRIMARY KEY ( idx )
)



서버프로그램(PHP)

서버프로그램은 클래스를 사용하기로 한다.
혹, 클래스가 잘 적응이 안되는 분도 이기회에 클래스를 한번 써보는것도 나쁘지는 않으리라 생각한다.
클래스를 설계할때 고민해야 할 것은 역할의 분리이다. 하나의 메소드에게는 한가지 일만 시키는것이 좋다.

직원 A에게 복사를 하는 일과 서류를 작성하는일, 거래처를 관리하는 일을 모두 맡겨왔는데
갑작스레 A가 사표를 낸다면

  1. A가 해왔던 세 가지 일을 모두 할 줄 아는 직원을 뽑거나
  2. 각각의 일을 맡을 세명의 직원을 뽑아야 한다.

하지만 처음부터 각 업무를 서로 다른 사람이 해왔다면 필요한 일만 할줄 아는 사람을 새로 뽑으면 된다.

우리의 주소록은 비교적 간단하므로 클래스를 구성하는데 별 무리가 없을것이다.
주소록 클래스가 할일을 살펴보면

  1. 주소록에 새로운 데이터 추가
  2. 입력된 데이터의 수정/삭제
  3. 입력된 데이터 추출

이상이다.

그럼 클래스를 만들어보자.

* 주소록 클래스는 PHP4도 호환이 가능하도록 작성할 예정이므로 __constructor__ 같은 PHP5전용 코드는 사용하지 않을것이다.

[class_addressbook.php]

class AddressBook{
   var $conn;

   //생성자
   function AddressBook($conn=Null){
       if($conn == Null){
           return false;
       }

       $this->conn = $conn;
   }

   //데이터 입력
   function addAddress(){}

   //데이터 수정
   function updateAddress(){}

   //데이터 삭제
   function deleteAddress(){}

   //데이터 추출
   function getAddress(){}
}

AddressBook 클래스의 기본 골격은 위와 같다.
DB연동이 주된 업무이니 생성자에서는 DB 커넥터를 기본으로 지정한다.

이제 메소드를 하나하나 구현해보자

1.데이터 입력: addAddress()

입력해야 할 필드는 총 4개인데 그중 idx는 자동으로 생성되니 addAddress 메소드에는 3개의 값만 던져주면 되겠다. 바로 이름,연락처,주소이다. 그중 주소는 NOT NULL 이 아니니 이점에 유의하자

function addAddress($name,$tel,$addr=Null){
   if(empty($name) == true || empty($tel) == true){
       return false;
   }
   //주소값이 주어지지 않으면 db에 null 을 입력한다. 공백을 입력하게 되면 is null 같은 검색이 안된다.
   if($addr == Null){
       $addr = 'null';
   }else{
       $addr = "'".$addr."'";
   }

   $qry = "INSERT INTO addressbook SET\n"
           ."name='".$name."',"
           ."tel='".$tel."',"
           ."addr=".$addr;

   $res = mysql_query($qry,$this->conn);

   //입력이 성공하면 해당 row의 index 번호를 반환한다
   if($res != false){
       return mysql_insert_id();
   }else{
       return false;
   }
}


2.데이터 수정: updateAddress()

데이터의 수정은 데이터의 입력과 비슷하다. 단지 어떤 데이터를 수정하느냐를 결정하는 idx가 주어지는 것만 다를뿐이다.

function updateAddress($idx,$name,$tel,$addr=Null){
   if(empty($idx) == true || empty($name) == true || empty($tel) == true){
       return false;
   }

   if($addr == Null){
       $addr = 'null';
   }else{
       $addr = "'".$addr."'";
   }

   $qry = "UPDATE addressbook SET\n"
           ."name='".$name."',"
           ."tel='".$tel."',"
           ."addr=".$addr."\n"
           ."WHERE idx=".$idx;

   return mysql_query($qry,$this->conn);
}


3.데이터 삭제: deleteAddress()


데이터의 삭제는 더 간단하다. 삭제할 row의 idx값만 주면 된다.

function deleteAddress($idx=Null){
   if($idx == Null){
       return false;
   }

   $qry = "DELETE FROM addressbook WHERE idx=".$idx;

   return mysql_query($qry,$this->conn);
}



4.데이터 추출: getAddress() + getAllAddress()

데이터 추출은 좀 다르게 구현을 해야 한다. 하나의 레코드만 추출 할 경우와 전체 레코드를 추출할 경우를 구분해야 하기 때문이다. 위에서도 하나의 말했듯 메소드에게는 하나의 일만 시키는 것이 좋으므로 데이터 추출은 두개의 메소드로 구현하기로 하자 getAddress()와 getAllAddress() 가 바로 그것이다.

function getAddress($idx=Null){
   if($idx == Null){
       return false;
   }

   $qry = "SELECT * FROM addressbook WHERE idx=".$idx;
   $res = mysql_query($qry,$this->conn);

   if(mysql_num_rows($res) > 0){
       return mysql_result($res,0);
   }else{
       return Null;
   }
}
function getAllAddress(){
   $qry = "SELECT * FROM addressbook";
   $res = mysql_query($qry,$this->conn);

   if(mysql_num_rows($res) > 0){
       $result = array();
       while($row = mysql_fetch_assoc($res)){
           array_push($result,$row);
       }

       return $result;
   }else{
       return Null;
   }
}

이제 필요한 메소드가 다 만들어졌다.
그런데 데이터 입력과 수정작업을 처리하는 메소드에 중복되는 코드가 보인다.
바로 SQL 쿼리문을 작성하는 부분인데 이부분은 따로 쿼리 작성 메소드를 만들어서 빼는게 좋겠다.
이름하여 캡슐화...

function makeQuery($name,$tel,$addr=Null){
   if(empty($addr) == true){
       $addr = 'null';
   }else{
       $addr = "'".$addr."'";
   }

   $str = "name='".$name."',\n"
         ."tel='".$tel."',\n"
         ."addr=".$addr;

   return $str;
}

캡슐화를 했으니 addAddress()와 updateAddress()메소드를 수정해야한다.
전체를 수정하는건 아니고 SQL쿼리 작성 부분만 수정하면 된다.

addAddress()
   $qry = "INSERT INTO addressbook SET\n";
   $qry .= $this->makeQuery($name,$tel,$addr);

updateAddress()
   $qry = "UPDATE addressbook SET\n";
   $qry .= $this->makeQuery($name,$tel,$addr);
   $qry .= " WHERE idx=".$idx;

드디어 AddressBook 클래스가 완성됐다.
사실 제대로된 객체지향 프로그래밍을 하자면 AddressBook 클래스 외에 Address 클래스도 필요하다.
하지만 지금까지의 과정도 쉽고 단순하게 하자는 당초의 계획과는 달리 복잡해진감이 없지않으므로 Address클래스는 일단 생략하고 클라이언트 프로그램 완성 후에 리팩토링을 하겠다.


테스트

DB에 테이블도 만들었고 클래스도 만들었으니 테스트를 해보자.
웹프로그래밍에 TDD(Test Driven Develope)적용이 필요한지에 대해서는 의견이 분분하지만 개념을 알필요는 충분하다고 본다.

에디터에서 다음과 같은 코드를 작성한 후 브라우져로 결과를 확인해보자.
<?php
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);
assert_options(ASSERT_CALLBACK, 'assert_handler');
assert_options(ASSERT_BAIL,1);

function assert_handler($file,$line,$code){
   echo "Assertion Failed:<br />
       File '$file'<br />
       Line '$line'<br />
       Code '$code'<br />";
}

include_once 'db_conn.php'
include_once 'class_addressbook.php';

echo 'start test<br />';

assert('$BOOK = new AddressBook($conn)');
echo 'class construction test ... [OK]<br />';

assert('$BOOK->addAddress("이효리","011-1111-1111")');
assert('$BOOK->addAddress("강동원","011-2222-2222","우리집")');
assert('$BOOK->addAddress("Jackson","060-3333-3333","America")');
echo 'address data INSERT test ... [OK]<br />';

assert('$BOOK->updateAddress(1,"이효리","016-4444-4444","우리집")');
assert('$BOOK->updateAddress(2,"강동웜","011-2222-2222","북한")');
echo 'address data UPDATE test ... [OK]<br />';

assert('$BOOK->getAddress(3)');
echo 'an address data GET test ... [OK]<br />';

assert('$BOOK->deleteAddress(3)');
echo 'an address data DELETE test ... [OK]<br />';

assert('$BOOK->getAllAddress()');
echo 'all address data GET test ... [OK]<br />';

echo 'All Test Success!!';

$qry = "DELETE FROM addressbook";
mysql_query($qry,$conn);

$qry = "ALTER TABLE addressbook auto_increment=1";
mysql_query($qry,$conn);
?>

브라우져에 All Test Success!! 가 출력됐다면 성공이다.

테스트가 성공했으면 실제 쓸 소스를 작성해야 한다.
이미 테스트 코드에서 다 만들었으니 그냥 가져다 쓰면 된다.

[execute_address.php]

//include =================================================
include_once 'db_conn.php';
include_once 'class_addressbook.php';


//request vars ============================================
$name = isset($_POST['name'])?$_POST['name']:Null;
$tel     = isset($_POST['tel'])?$_POST['tel']:Null;
$addr  = isset($_POST['addr'])?$_POST['addr']:Null;
$idx    = isset($_POST['idx'])?$_POST['idx']:Null;
$job    = isset($_POST['job'])?$_POST['job']:Null;

$result = false;

if($job == Null || false !== $BOOK = new AddressBook($conn)){
   switch($job){
       case('add'):
           $result = $BOOK->addAddress($name,$tel,$addr);
       break;

       case('update'):
           $result = $BOOK->updateAddress($idx,$name,$tel,$addr);
       break;

       case('delete'):
           $result = $BOOK->deleteAddress($idx);
       break;

       case('get'):
           $result = $BOOK->getAddress($idx);
       break;

       case('get_all'):
           $result = $BOOK->getAllAddress();
       break;
   }
}


준비끝

아직 완성은 아니지만 서버쪽 코딩이 끝났다.
완성이 아니라고한 이유는 php 처리 결과를 javascript 로 보내는 코드가 빠졌기 때문이다.
이 부분은 클라이언트 코딩할때 추가하기로 한다. 한글 인코딩 문제도 있고 JSON과 XML등등 데이터 가공과정을 거쳐야 하기때문이다.

여기까지는 그리 힘들지 않을것이라 본다.
어려운 부분은 없었던것 같고, 다만 클래스나 assert() 함수가 낯선 분들이 있을지도 모르겠다.
다음 포스팅에서는 AJAX애플리케이션의 핵심인 클라이언트 코딩을 하겠다.
DOM을 많이 사용해야하니 DOM에 자신 없는 분은 미리 [DOM]에 대해 공부를 하시길...
다음 링크를 따라가면 DOM에 대해 배울수 있다.

DOM3 - http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/Overview.html#contents
DOM3 Event - http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html
HTML DOM - http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-39872903

posted by 초딩입맛제주아재
2007. 3. 28. 13:22 Programing/HTML/JavaScript/CSS

개요

이번에 AJAX 실전 테스트용 주소록 코드를 만들면서 배열의 remove 기능이 필요해서 Javascript API를 보니 Array 객체에 remove 메소드가 없다.(혹시 필자가 못찾은 거라면 낭패 -_-.... 찾은분은 알려주시길..)
코어에서 지원이 안되니 직접 만들수 밖에 없었다.
본인이 손수만든 Array.remove() 메소드를 공개한다.
누누히 당부드리지만 본인은 신이 아니고 프로그래밍 도사도 아니기에 실수도 할 수 있고 효율이 떨어지는 코드를 남발할수도 있다. 조언과 지적은 감사히 수용하겠으나 막가파식 테클은 반사다...:)


발단

주소록의 정보를 배열에 담았다가 삭제할때 인덱스를 테이블 ROW(tr)과 일치시켜 주어야 하기때문에
인덱스의 재정렬이 필요했다.

* tableSection.deleteRow() 메서드는 자동으로 ROW의 인덱스가 재정렬한다.
* http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-67417573 참고.


사용자 삽입 이미지

주소록 리스트 - 여기서 데이터를 삭제하면...

사용자 삽입 이미지
사용자 삽입 이미지

테이블 ROW 가 삭제되고 주소록 정보를 담았던 배열에서도 해당 데이터를 담고 있는 원소가 삭제된 후 인덱스를


전개

배열의 원소를 삭제하고 인덱스를 정렬하는 알고리듬을 생각해보면 다음과 같은 절차를 거친다.

  1. 삭제할 원소의 인덱스 직전까지의 원소들과 이후의 원소들을 분리시킨다.
  2. 분리된 원소들을 하나의 배열로 합친다.
원리는 무척 간단해 보인다.
방법이 문제다.
어떻게 배열을 둘로 나눌지...

본인은 API를 보던중 slice 라는 메소드를 찾았다.

출처 : http://www.w3schools.com/jsref/jsref_slice_array.asp

Definition and Usage

The slice() method returns selected elements from an existing array.

Syntax

arrayObject.slice(start,end)

Parameter Description
start Required. Specify where to start the selection. Must be a number
end Optional. Specify where to end the selection. Must be a number


Tips and Notes

Tip: You can use negative numbers to select from the end of the array.

Note: If end is not specified, slice() selects all elements from the specified start position and to the end of the array.


이 메소드를 사용하면 간단하게 해결될것 같지 않은가?

그리하여 다음과 같은 코드를 만들었다.

   //addressbook 는 주소록 정보를 가지고 있는 배열이다.

   var temp_head = addressbook.slice(0,rowIndex);
   var temp_body = addressbook.slice(rowIndex + 1);

   for(var i=0; i<temp_body.length; i++){
       temp_head.push(temp_body[i]);
   }

   addressbook = temp_head;

주의해야 할점은 slice메소드의 첫번째 인자와 두번째 인자의 시작 위치가 다르다는 것이다.
start값은 0부터 시작하는 배열의 첨자값을, end값은 1부터 시작하는 배열의 length 값을 의미한다.



절정

위 코드를 만들고 나니 아무래도 remove 기능을 모든 배열에서 쓰게 하는게 낫겠다는 생각이 들었다.
Array객체에 prototype으로 remove 메서드를 추가하기로 했다.

Array.prototype.remove = function(index){}

처음엔 위의 코드를 그대로 복사해서 가져다 붙였다. Ctrl + c, Ctrl + v 신공...

[code 1]

  var temp_head = this.slice(0,index);
   var temp_body = this.slice(index + 1);

   for(var i=0; i<temp_body.length; i++){
       temp_head.push(temp_body[i]);
   }

   this = temp_head;


어째 좀 이상하지 않은가??
자신이 소유하고 있는 메소드에서 자신을 바꾸려하다니....
익스플로러에서는 this에 할당 할 수 없다는 오류가 발생한다.
시도 자체가 말이 안되는 행위였다...-_-;;

그래서 다음과 같은 알고리듬을 생각했다.
  1. 위,아래 원소를 분리하고 합치는것까지는 동일
  2. 원본배열의 원소를 전부 제거
  3. 새로 만들어진 배열의 원소를 원본배열에 모두 추가
[code 2]

   var temp_head = this.slice(0,idx);
   var temp_body = this.slice(idx + 1);

   for(var i=0; i<temp_body.length; i++){
       temp_head.push(temp_body[i]);
   }

   while(this.length > 0){
       this.pop();    //shift 를 사용해도 된다.
   }

   while(temp_head.length > 0){
       this.push(temp_head.shift());
   }

이제 제대로 작동한다~

그런데 웬지 모르게 메소드가 지저분해 보인다.
for에 while이 두개씩이나...반복문이 세번이나 돌아간다...

그리하여 또 다시 머리를 쥐어짰다.
  1. 원본 배열에서 주어진 인덱스부터 마지막 원소까지 모두 추출한다.
  2. 추출된 배열에서 마지막 원소는 제거할 원소이므로 빼버린다.
  3. 남은 원소들을 원본 배열에 추가한다.
  
[code 3]  

   var temp = new Array();
   var i = this.length;

   while(i > idx){
       var kk = this.pop();
       temp.push(kk);

       i--;
   }

   temp.pop();

   while(temp.length > 0){
       this.push(temp.pop());
   }


결말

[code 2]와 [code 3] 의 효율성의 차이는 정확히 파악하지 못했다.
단지 보기에 깔끔하고 반복문을 한번 덜 쓴다는 이유로 [code 3]을 주소록에 적용을 했다.

[code 3]의 경우 아직 리팩토링의 소지가 있는데 바로 두번째 while 블럭 이다.
조건절에서는 함수나 메소드의 호출을 지양해야 하기 때문인데

다음과 같이 수정 할 수 있다.

   var temp = new Array();
   var i = this.length;

   while(i > idx){
       var kk = this.pop();
       temp.push(kk);

       i--;
   }

   for(var i=temp.length - 2; i>=0; i--){
       this.push(temp[i]);
   }

중간에 temp.pop()이 필요가 없어졌고 for문을 사용한다.
조건절에서는 i가 0이상인지만 비교하면 된다.

사용예)

<script type="text/javascript">
Array.prototype.remove = function(idx){
   var temp = new Array();
   var i = this.length;

   while(i > idx){
       var kk = this.pop();
       temp.push(kk);

       i--;
   }

   for(var i=temp.length - 2; i>=0; i--){
       this.push(temp[i]);
   }
}

var arr = new Array(6)
arr[0] = "Jani"
arr[1] = "Hege"
arr[2] = "Stale"
arr[3] = "Kai Jim"
arr[4] = "Borge"
arr[5] = "Tove"

document.write(arr + "<br />")
arr.remove(1);
document.write(arr + "<br />")
</script>

posted by 초딩입맛제주아재
2007. 3. 14. 23:10 Programing/HTML/JavaScript/CSS

AJAX가 무엇인지는 검색을 통해 쉽게 찾을 수 있으니 생략하기로 한다.
다만 한가지 당부의 말을 하고 싶어 몇자 적는다.

당신이 AJAX에 대하여 무엇을 상상했건 당신이 상상한 그 이상도 그 이하도 아닐것이다.
AJAX는 혜성처럼 등장한 새로운 언어도 아니고 무언가 획기적인 방법으로 화려한 어플리케이션을 개발하게 해주는 기술도 아니다.

꼭 위의 말을 기억하길 바란다.
기대가 크면 실망도 크니까....

내가 이 포스팅을 하게 된 이유는 아직 AJAX를 잘 모르는 친구놈에게 AJAX를 가르치기 위함이다.
때문에 글 내용은 차분하면서도 세세하게 예제를 통해 AJAX에 대해 설명할 것이다.


준비

앞으로 AJAX를 설명하면서 만들 어볼 예제는 주소록이다.

본 내용과는 관련이 없지만 혹시 Ruby on Rails 를 모르지만 해보고 싶은 분은
여기를 클릭해서 주소록 예제를 해보시길 :)

주소록의 구조는 간단하다.
빈 주소록에 새 레코드를 작성하고 작성된 레코드를 수정하거나 삭제하는 기능이 전부다.
물론 이 모든 작업은 AJAX를 사용하여 페이지 이동 없이 하나의 열려진 페이지 내에서 이루어질것이다.

그럼 본격적으로 시작....



시작

우선 AJAX의 핵심(나는 이것이 핵심이라고 생각한다.)인 XMLHttpRequest 객체에 대해 알아보자.


XMLHttpRequest

property:

onreadystatechange Sets or retrieves the event handler for asynchronous requests.
readyState Retrieves the current state of the request operation.
responseBody Retrieves the response body as an array of unsigned bytes.
responseText Retrieves the response body as a string.
responseXML Retrieves the response body as an XML Document Object Model (DOM) object.
status Retrieves the HTTP status code of the request.
statusText Retrieves the friendly HTTP status of the request.

method:
abort Cancels the current HTTP request.
getAllResponseHeaders Returns the complete list of response headers.
getResponseHeader Returns the specified response header.
open Assigns method, destination URL, and other optional attributes of a pending request.
send Sends an HTTP request to the server and receives a response.
setRequestHeader Adds custom HTTP headers to the request.


각각의 속성과 메서드들은 MSDN에서 자세하게 설명하고 있다.

XMLHttpRequest 객체는 브라우져마다 생성방법이 조금씩 다르다.

IE 6이하의 버전에서는 다음과 같다.

new ActiveXObject('Msxml2.XMLHTTP')
new ActiveXObject('Microsoft.XMLHTTP')


IE 7부터 XMLHttpRequest을 지원하며 파이어폭스,사파리등에서는 이미 지원하고 있다.
따라서 이들의 브라우져에서의 생성 방법은 다음과 같다.

  new XMLHttpRequest();


이걸 한데 묶어보면 다음과 같다.
var request = false;

try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
XMLHttpRequst 객체가 만들어졌다.
서버와 클라이언트가 데이터를 주고 받을 수 있는 길이 열린것이다.
앞으로 저 길 위에서 주소록에 사용될 데이터들이 왔다리 갔다리 할 것이다.
이번 순서는 길을 연것으로 만족하자.
그리고 XMLHttpRequest 객체의 속성과 메서드들을 꼼꼼히 살펴보기 바란다.
인터넷에서 흔하게 찾을 수 있는 누군가에의해 만들어진 함수를 쓰는 것도 나쁘지는 않으나 적어도 XMLHttpRequest 객체의 각 속성과 메서드의 역할은 제대로 알고 있어야 할 것이다.

다음 순서에서는 주소록을 위한 서버 프로그램(PHP)과 클라이언트 프로그램(HTML)을 만들어 볼 것이다.
posted by 초딩입맛제주아재
2007. 3. 9. 09:58 Programing
원문: http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=29020

언어에 대한 유연한 태도가 필요
필자가 볼 때 모든 영역을 다 커버하고 모든 상황에 잘 들어맞는 최고의 언어란 존재할 수 없다. 모든 언어는 각자의 장점을 가지고 있다. 그것이 가장 잘 활용되어질 수 있는 상황과 영역이 제각기 따로 있는 것이다.
스크립트 언어는 한때 그 개발자는 프로그래머가 아니라 스크립터라고 비하될 정도로 무시되어져 왔다. 하지만 그런 오만함은 결국 기존 언어 개발자 스스로의 발등을 찍는 결과로 돌아왔다. 최고급의 아키텍처와 기술이라고 자랑하고 떠들썩했던 EJB가 결국 실패를 하고 초라해진 지금 개발자들은 언어와 기술을 대하는 자신의 자세에 대해서 다시금 진지하게 생각을 해야 할 것이다.
프로그래밍 언어는 그 자체의 장점을 증명하고 드러내기 위해 만들어 진 것이 아니다. 프로그래밍 언어는 그것을 이용해서 어떤 문제를 풀어내고 개발자들이 편리하게 개발할 수 있도록 해주는 도구로 활용될 때 가장 가치 있는 것이다. 그런 면에서 기존 언어가 낫다거나 스크립트 언어가 좋다는 식의 ‘언어 순수주의’적인 태도를 가진 경쟁은 지양해야 한다.
오히려 지금 많은 유연한 사고를 가진 개발자들에 의해서 만들어지고 있는 언어 상호간의 결합과 확장에 대한 노력을 지지해야 한다. 특히 그동안 개발자를 힘들게 했던 많은 고민들을 해결해 줄 수 있는 장점을 가진 스크립트 언어에 관심을 가지고 그것을 포용하려는 노력이 절실하게 필요하다.


(원문 발췌)

역시 결론은 언어==도구 라는것.
한해,두해 지나니까 저절로 알게 된다.
특정언어에 얽매여서는 안된다는걸.
유연한 프로그래머가 되어야 한다는걸.

posted by 초딩입맛제주아재
prev 1 2 3 4 5 6 7 ··· 11 next