부제 : Javascript prototype은 어떤 의미를 갖는가?


MDC defined
Prototype is a property of various Javascript Objects
Prototype은 다양한 자바스크립트 오브젝트의 프로퍼티이다.

그럼 오브젝트는 무엇일까요?

object

An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

Object Object의 타입type맴버입니다그것은 기본적인 value이나 오브젝트object, 함수function 각각 프로퍼티의 무질서한 컬렉션입니다.

오브젝트의 속성에 지정된 함수는 메서드method라 불린다.


다시 MDC 에서 정의한 프로토타입에 대한 설명입니다.

프로토타입prototype ECMAScript에서 구조structure, 상태status, 습성behavior 구현하기 위해 사용하는 오브젝트object입니다.

생성자constructor는 오브젝트를 생성할 때 그 오브젝트에 프로퍼티 레퍼런스를 가리킬 목적으로 생성자constructor의 연관된 프로토타입prototype 을 참조하게 됩니다.

생성자constructor와 연관된 프로토타입prototypeconstructor.prototype과 같이 프로그램program적인 표현expression 으로 참조 될 수 있고 native Object의 프로토타입prototype에 추가되어진 프로퍼티properties가 공유shared되어 집니다.


Constructor

생성자constructor생성create하고 초기화initialize하는 함수 오브젝트입니다각각의 생성자는 상속구현과 공유 프로퍼티 사용을 위해 연관된 프로토타입prototype 오브젝트를 갖습니다.


사용자 삽입 이미지

prototype 이라는 것은
javascript의 표준인 ECMAScript의 오브젝트 중 하나입니다.



이렇게 정의를 하고 계속해서 좀더 상세히 알아보도록 합니다.


ECMAScript는 C++, Smalltalk, Java 처럼 클래스의 개념이 존재하지 않지만 오히려 오브젝트를 위해 스토리지를 할당하고 그들의 프로퍼티에 초기값 할당을 통해 그것들의 일부 혹은 모든것을 초기화하는 실행 코드로 오브젝트를 만드는 생성자를 제공합니다.

생성자를 포함하는 모든 함수들은 오브젝트이지만 모든 오브젝트가 생성자가 되는 것은 아닙니다.

각각의 생성자constructor는 프로토타입 기반prototype-based 상속inheritance과 공유shared 프로퍼티properties를 구현하기 위하여 프로토타입 프로퍼티 갖습니다.

오브젝트는 new 연산자에 생성자를 사용하여 생성되어짐 : 예를 들어 new String(“A String”)는 새로운 string 오브젝트를 생성합니다.

new를 사용하지 않고 생성자를 적용하는 것은 생성자에 따른 결과를 갖습니다.

예를 들어 String(“A String”) 는 초기 문자열이 만들어집니다. 하지만 오브젝트는 아닙니다.

ECMAScript는 프로토타입 기반prototype-based 상속inheritance을 지원합니다.

모든 생성자는 연관된 프로토타입을 가집니다. 그리고 생성자에 의해 생성되어진 모든 오브젝트는 생성자와 연관된 프로토타입(Object’s prototype 이라 불리우는)에 절대적인 레퍼런스를 갖습니다.



사용자 삽입 이미지



더욱이 프로토타입prototype은 null이 아닌 원형prototype에 절대적인 레퍼런스를 갖습니다. 그래서 이것을 프로토타입 체인prototype chain 이라고 부릅니다.

오브젝트에서 레퍼런스reference가 프로퍼티property에 만들어 질 때 저 이름의 프로퍼티를 포함하는 프로토타입 체인chain의 첫번째 오브젝트에 저 이름으로 프로퍼티를 갖는다.



사용자 삽입 이미지


바꿔 말하면,  

첫번째는 오브젝트가 직접 언급했던 프로퍼티가 있는지 없는지 조사(검토)하는 것입니다.  만약 오브젝트가 정해진 프로퍼티를 포함한다면 그 레퍼런스가 참조하는 프로퍼티입니다.  만약 그렇지 않다면 오브젝트는 찾기 위해서 다음 프로토타입prototype으로 넘어간다

즉 위의 예제 소스를 예로 설명하자면 마지막에  childObject.name.toString(); 를 호출했습니다.
최초 childObject가 가지고 있는 name을 참조합니다. childObject에는 name 프로퍼티를 가지고 있기 때문에  toString()을 수행하게 됩니다. 만약 name 프로퍼티가 존재하지 않는다면 fatherObject -> grandFather -> Object 까지 찾아가게 되겠죠.

아무튼 name 프로퍼티가 존재하므로 childObject에는 toString()이라는 메서드를 수행하게 됩니다. 하지만 childObject 에는 toString() 이라는 메서드가 존재하지 않기 때문에 Object.prototype.toString()을 수행하게 됩니다. 만약 Object.prototype.toString 메서드가 존재하지 않는다면 당연히 (fireBug)toString is not a function 이라는 메세지를 보게되겠죠.


그래서 클래스 기반class-based 객체 지향 언어는 일반적으로 인스턴스instance에 의해 이동된 상태, 클래스에 의해서 이동된 메서드 그리고 상속은 구조와 습성의 유일함이다.

ECMAScript에서 상태와 메서드들은 오브젝트에 의해서 이동되어 집니다그리고 구조, 습성, 상태는 모두 상속되어 집니다.

직접 그것들의 프로토타입prototype이 포함하는 특별한 프로퍼티property를 포함하지 않는 모든 오브젝트들은 저 프로퍼티와 그 값value을 공유한다.

아래 다이어그램을 참조

사용자 삽입 이미지


CF는 생성자 입니다(그리고 또한 오브젝트 입니다.).

다섯개의 오브젝트는 new 연산자를 통해 생성 : CF1, CF2, CF3, CF4, CF5

각각의 오브젝트는 q1, q2의 프로퍼티를 포함합니다. 점선 라인은 절대적인implicit 프로토타입prototype 관계; 예를 들어 CF3의 프로토타입은 CFp입니다.


그 생성자 CF는 자체적으로 CFp, CF1, CF2, CF3, CF4, CF5에 보이지 않는 2개의 프로퍼티를 갖습니다.

CFp 안에 CFp1 프로퍼티는 q1, q2 혹은 CFp1라 지정되지 않는 CFp의 절대적인 프로토타입 체인에서 발견되어지는 어떤 프로퍼티들 처럼 CF1, CF2, CF3, CF4, CF5에 의해서 공유되어 집니다.

CFp CF 사이에 절대적인 프로토타입 링크가 없다는 것을 알아야 합니다.

클래스 기반 언어들과는 달라 프로퍼티들은 값을 할당하는 것으로 오브젝트에 동적으로 추가될 수 있습니다.

즉 생성자는 생성되어진 오브젝트의 프로퍼티 일부분 혹은 전체에 이름과 값의 할당하는 것을 요구하지 않습니다.

위의 다이어그램에서, 한가지 CFp에 프로퍼티에 새로운 값을 할당하는 것에 의해 CF1, CF2, CF3, CF4, CF5를 위한 새로운 공유된 프로퍼티를 추가할 수 있다.


모두 ECMAScript 262-2 Spec 자료입니다.
중간에 번역의 이해를 돕고자 이미지화 하였습니다.  혹 이미지화 한 것이 혼동을 잃으킬 수도 있습니다. ^-^;
오역이 있을 수 있지만 최대한 번역에 대한 점검을 하였습니다. (외국에 살다온 직장 동료에게 검증을 받았습니다. ^^;;)

신고
Posted by Rhio.kim
Class-Based vs Prototype-Based Languages

사용자 삽입 이미지
과연 자바스크립트 OOP에 대한 이해도를 조금 높히는데 도움이 될까 번역해 보았습니다.  경우에 따라 오역이 있을 수도 있습니다.  또한 완벽하지 않다는 말이 될 수도 있습니다.

원글은 아래 링크를 기재해 두었습니다.  이번 글을 개념적인 부분을 설명하고 있어 글로만 표현하였습니다.  이미지를 첨부해 좀더 이해도를 높이려고 했으나.. 힘들어서 포기 ^-^;

우리가 흔히 알고 있는 객체 지향 언어인 Java 와 C++ 의 간단한 비교가 아래부분의 표로 기재되어있습니다.   하지만 기재된 것이 차이점의 전부라고 할 수는 없습니다.

언어와 다른 언어를 비교해가며 OOP가 된다 안된다를 거론하지는 않았으면 합니다.
또한 어느 언어나 객체지향이 가능하다라고 말하고 싶습니다.  마지막으로 OOP에 대한 비교 우위를 따지는 것은 단지 수치화 해보고 싶은 마음에서만 하는것이 좋다고 생각합니다.

Java와 C++과 같은 클래스 기반 객체지향 언어는 두 가지의 뚜렷한 본질적인 개념을 갖는다.

클래스
1.    하나의 클래스는 포함하는 일련의 오브젝트들의 특성을 나타낼 프로퍼티Property 모두를 정의한다.  클래스는 일련의 오브젝트의 특정 맴버들에 비해 더 추상적인 것이다.  예를 들면 사원 클래스는 모든 사원들의 구성을 표현할 수 있다.

관련정보 : http://en.wikipedia.org/wiki/Class_(computer_science)

인스턴스
1.    반면에 인스턴스instance는 클래스의 인스턴스 즉 맴버중에 하나입니다.  예를 들어 사원 클래스의 인스턴스로 특정한 개개의 직원을 표현할 수 있습니다.
2.    인스턴스는 부모 클래스의 속성을 정확하게 갖고 있습니다. (그 이상도 그 이하도 아님)


클래스 정의

자바스크립트 같은 프로토타입 기반prototype-based 언어는 이렇게까지 구분하지 않습니다. : 단순히 오브젝트Object를 같습니다.

프로토타입 기반 언어는 prototype 오브젝트의 개념을 갖습니다.  개체를 사용하는 템플릿으로써 새로운 오브젝트를 위한 초기 프로퍼티를 얻기 위해 사용됩니다.

모든 오브젝트는 생성할 때나 런타임 때 자신의 속성을 지정할 수 있습니다. 또한 모든 오브젝트는 prototype 통해서 다른 오브젝트에 연결 될 수 있고 두 번째 오브젝트에 첫 번째 오브젝트의 프로퍼티를 공유하도록 허락합니다.

클래스 기반 언어, 별도의 클래스로 정의합니다.
이 정의는 여러분이 클래스의 인스턴스를 생성하기 위해서 특별한 메서드를 지정하고 생성자를 호출합니다.  생성자 메서드는 초기값을 지정할 수 있고 생성 주기에 다른 처리를 할 수 있습니다.

여러분은 클래스의 인스턴스를 생성하기 위해 생성자 함수와 관련된 new 오퍼레이터를 사용합니다.

자바스크립트 또한 같은 모델이지만 생성자로부터 별도의 클래스 정의를 갖지 않습니다.  대신에 사용자는 오브젝트를 생성하기 위해서 특정한 초기 프로퍼티와 값의 구성을 정의합니다.  모든 자바스크립트 함수는 생성자처럼 사용될 수 있습니다.  새로운 오브젝트를 만들기 위해서 new 오퍼레이터로 생성자 함수를 사용하면 됩니다.


서브클래스subclass와 상속inheritance

클래스 기반 언어는 클래스의 정의를 통해 클래스 계층hierarchy 구조를 만듭니다.  클래스의 정의에 이미 존재하는 클래스의 하위 클래스로 새로운 클래스를 지정할 수 있습니다.  서브 클래스는 슈퍼 클래스의 모든 속성을 상속 받습니다.  또한 추가적으로 새로운 속성을 부여하거나 상속 받은 것들 것 수정할 수도 있습니다.

예를 들어 직원 클래스는 이름과 부서의 속성만 갖고 하위 클래스인 관리자는 보고 속성을 추가합니다.  이 경우 관리자 클래스의 인스턴스는 세가지 모든(이름, 부서, 보고) 속성을 갖게 됩니다.

자바스크립트는 prototypical 오브젝트를 어떤 생성자 함수와 연결시키는 것을 통해서 상속을 구현한다.

그래서 직원-관리자 예제를 정확하게 만들 수 있습니다.  하지만 약간의 다른 용어를 사용합니다.  직원 생성자 함수를 정의하고 이름과 부서 속성을 지정합니다.  그런 다음 관리자 생성자 함수를 정의하고 보고서 속성을 지정합니다.  마지막으로 관리자 생성자 함수를 위해 prototype에 새로운 직원 오브젝트를 할당합니다.  여러분이 새로운 관리자를 생성할 때 직원 오브젝트로부터 이름과 부서의 속성을 상속 받습니다.


속성 추가addding 및 제거removing

클래스 기반 언어는 전형적으로 컴파일 될 때 클래스가 생성됩니다.  그렇지 않으면 클래스의 인스턴스는 컴파일 시간 또는 런타임 시에 인스턴스화 됩니다.  클래스의 정의된 후에는 클래스의 속성 타입이나 숫자를 변경할 수 없습니다.  그러나 자바스크립트에서는 런타임 시에 어떤 오브젝트의 속성을 추가하거나 삭제할 수 있습니다.
한 구성의 오브젝트를 위해 prototype으로 사용되는 오브젝트에 프로퍼티를 추가하면 그것이 프로토타입인 오브젝트들 또한 새로운 프로퍼티를 얻는다.

클래스 기반 (자바)

프로토 타입 기반 (자바 스크립트)

클래스와 인스턴스는 별개의 엔티티이다.

모든 오브젝트는 인스턴스이다.

인스턴스는 생성자 메서드와 갖는

생성자 함수를 갖는 일련의 오브젝트를 정의하고 생성

new 연산자로 단일 개체 생성

동일

기존 클래스들의 하위 클래스를 정의하기 위해 클래스 정의에 의한 오브젝트 계층 생성

생성자 함수와 관련되어 프로토타입으로 오브젝트를 할당하므로써 오브젝트의 계층구조를 생성

클래스 체인으로 프로퍼티 상속

프로토타입 체인에 따라 프로퍼티를 상속

클래스 정의는 클래스의 모든 인스턴스의 모든 속성을 지정합니다.  동적 런타임 시에는 속성을 추가할 수 없다.

생성자 함수 혹은 prototype은 일련의 속성을 지정합니다. 단일 오브젝트 혹은 일련의 오브젝트들에 동적인 메서드 추가 및 삭제할 수 있습니다.


참조 자료 : http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Class-Based_vs._Prototype-Based_Languages

신고
Posted by Rhio.kim
Prototype 1.5.1.1 의 Ajax 중복 요청에 대한(XHR Request managment)를 만들어 보았습니다.
자세한 내용은 아래를 참고해 주세요.

  문제제기
    네트워크 병목 현상이나 서버의 부하로 인하여 XHR(XMLHTTPRequest)의 Response가 늦어져
    사용자에 의해서 동일한 중복 요청이 발생할 경우

    e.g) Ajax 게시판에서 사용자는 1페이지에서 2페이지로 이동하는 단계에서 요청한 2페이지의 결과가
           Response 되기 전에 3페이지를 누르는 경우 2페이지의 XHR는 의미 없는 요청이 된다.

  해결방안 모색
    new Ajax.Request가 발생한 다는 것은 Ajax.Request.initialize() 생성자 함수가 호출되면서
    XHR 이 Request를 발생시키는데 이때 아래 시나리오를 추가하여 해결한다.
사용자 삽입 이미지


  시나리오
    1. 현재 개발되어진 소스에 영향을 받으면 안된다.
    2. Ajax._observers 배열에 이미 요청중인 요청이 있는 체크하여 있다면 현재의 요청과 비교한다.
        만약 있다면 3, 없으면 6
    3. 다음 Ajax.Request가 동알한 url 로 생성되어 질때 이미 쌓아 놓은 배열에 동일한 URL로 요청중인
        XHR에 abort() 이벤트를 발생시켜준다.
    4. 해당 Ajax.Request 오브젝트는 null로 변경한다.(메모리 누수 발생 될 수 있음)
    5. abort가 발생한 Ajax.Request 오브젝트 레퍼런스는 배열에 splice로 삭제한다.
    6. new Ajax.Request() 가 발생할 때 Ajax.Request 오브젝트의 레퍼런스를 배열
        Ajax._observers에 쌓는다.
    7. 정상 완료된 Ajax.Request가 있다면 Ajax.Responder에 의해서 사용자 등록한 responders 배열 중
        해당 callback method "onComplete"를 호출한다.
    8. Ajax._observers에 쌓아두었던 Ajax.Request 오브젝트의 레퍼런스를 소멸시켜준다.

예제
신고
Posted by Rhio.kim
Prototype Core team 멤버인 Tobie Lange씨는 Prototype 1.5 버젼 버젼에서 1.6으로 업그레이드 하려고 할때 API 변경이나 어떤 사용하지 못하는 것들에 대해서 경고해주는 스크립트를 개발하였습니다.

이 스크립트는 Firebug의 콘솔을 이용하기 때문에 Firebug에서만 동작을 합니다.

사용자 삽입 이미지

사용법은 1.5에서 1.6으로 변경할 페이지에서

1. prototype.js 를 추가한 태그 즉
   <script src="prototype.js"> 바로 아래로
2. deprecation.js 를 추가합니다.
   <script src="deprecation.js">
3. 그리고 디버깅과 함께 개발하면 됩니다.

이렇게 하면 위와 같은 console에 잘못 사용하거나, 변경되거나, 수정되거나 한 exception message가 계속 쌓입니다. 

개발은 계속 하되 단지 console의 로그 메세지만 출력하지 않을 거라면..

4. DeprecationNotifier.logDeprecation = false; 로 하면 log가 남지 않습니다.

원      문 : http://prototypejs.org/2008/2/12/deprecation-js-easing-the-1-5-1-6-transition
다운로드 : http://prototypejs.org/assets/2008/2/12/deprecation.js

신고
Posted by Rhio.kim
사용자 삽입 이미지
TPuzzle 이후 새롭게 탄생할 TFastClick Ajax Game 입니다.
TPuzzle 는 Ajax로 구현된 네트워크 게임으로 만들어 보려는 목표가 있었으나 언젠지 모르게 제 관심밖으로 점점 멀어져 버렸습니다.

그래서 이번 게임은 매우 간단하면서도 "사람 짜증나게 하는 게임"입니다. 

플래시로 구현해놓은 게임이 있어서 짬을 내서 javascript 로 구현해보았습니다.

간단한 룰은 랜덤으로 생성되는 숫자를 순서대로 클릭하는 게임입니다.

생각보다 20초안에 성공하기는 쉽지가 않더군요. ^^;;
그래서 목표 "PlayTime"는 17초입니다.

사람의 눈과 사람의 뇌의 단순함을 느낍니다. ㅋㅋㅋ

아직 구현되지 않는 부분이 있어서 이번주 중에 공개할 예정입니다.

DB 연동으로 순위 저장이 되어야 하기 때문에 그부분 구현이 남아있고 Effect 부분이 빠져있어 아직 보잘 것 없습니다.

하지만 잘못하면 잘못하면... 빠져든다는 것.. 중독성이 강할지도 모르고 오기가 발동하여 회사에서 일하다 말고
17초라는 기록을 깨기 위해 점심시간에도 이것을 하고 있는 당신을 볼지도 모릅니다.

전적으로 이런분들은 건강에 해를 미칠 수도 있으며 그에 대한 책임은 절대로 본인에게 있습니다.

신고
Posted by Rhio.kim
사용자 삽입 이미지
  프로토타입 기반의 아주 가볍고 빠르고 사용하기 간편한 캘린더 입니다.

여러개의 캘린더를 충돌없이 사용할 수 있습니다.

유효한 HTML/XHTML 생성 코드를 사용하고 있어서 크로스 브라우징에도 문제가 없네요..

이미지에서도 볼 수 있듯이 아주 심플리트 그자체입니다.

저도 이런걸 추구합니다. 요즘은 더무 복잡하고 광범위한 옵션을 제공하는 프로토타입 기반의 라이브러리들이 많이 나옵니다.  왜 국내에는 없을까요??
회사일에 바쁘셔서 그런거 할 시간이 없다?? ^-^*

외국에서는 Prototype 프레임웍의 인지도가 상당히 높은데요.
최근에 나오는 대부분의 라이브러리들은 Prototype, Script,aculo.us 를 이용하고 있습니다.

몇가지 추가적인 기능으로는 스킨기능, 다국어 지원, 이벤트 계획기능도 포함합니다.
참 캘린더가 갖을 수 있는 컴팩트한 기능은 모두 지원하는 군요...

사용법은 매우 간단합니다.   라이브러리 파일을 로드하고 아래와 같이.

<div id="samplecal" class="scal"></div>
<div id="scalupdate">&nbsp;</div>

var samplecal = new scal('samplecal', 'scalupdate');


원본출처 : http://scal.fieldguidetoprogrammers.com/
다운로드 : http://scal.fieldguidetoprogrammers.com/files/scal_0.2.zip
신고
Posted by Rhio.kim
사용자 삽입 이미지
몇일전 1.6.0 정식버젼으로 릴리즈 된 Prototype.js 의 변화 중 Event 오브젝트의 사용자 이벤트부분이 있습니다.
OOP 개발을 하다보면 이벤트 밖의 처리와 이벤트 안의 처리 좀 더 자세히 말하자면

리스너와 핸들러 핸들러 Scope 안과 밖에서 일어나는 모든 일들을 처리하자면 어려운 점들이 간혹 생깁니다.
예를 들어 Scope 안의 this와 밖의 this 분명 차이가 있죠...

아 이건 사용자 이벤트와는 무관하니 넘아갑니다.


이벤트 리스너 등록(Observing events)

<img src="./test_off.gif" onmouseOver="this.src='./test_on.gif'" onmouseOut="this.src='./test_of.gif'" />

<input type="button" onclick="javascript:buttonClick(event);" id="button" value="Ok"/>
<script type="text/javascript">
    function buttonClick(event){
        alert(event);
    }
</script>

우리는 iniline 스크립트로 대부분 이런식의 이벤트를 줍니다. 하지만 web2.0방식의 oop 개발에 있어서는
그 다지 추천할만한 방법은 아니라고 보여집니다.

Prototype.js 에서 지원하는 이벤트 Observing

<div id="test"></div>
<script type="text/javascript">
    Element.observe('test', 'mouseover', bgChange);  <-- target Element id 를 통한 mouseover 리스너 설정

    $('test').observe('mouseover', bgChange);  <-- target Element 에 mouseover 리스너 설정

    function bgChange(event){
        var targetElement = Event.element(event);  <-- 1.6.0 에서는 var targetElement = event.target;
    }
</script>

이 벤트 리스너와 핸들러에 대한 구분과 실제 DOM 레벨 addEventListener, dipatchEventListener 등을 알아야합니다. 프레임웍의 편리한 점도 있지만 원천적으로 알아야할 부분을 모르고 사용한다면 코더에 불과해집니다.



사용자 이벤트(custom events)

대부분에 잘 알려진 Javascript 프레임웍에서는 이미 사용자 이벤트가 있습니다. 그리고 Prototype에 적용되기 전에 매우 긴 방법을 사용했습니다. Prototype.js 의 사용자 이벤트는 다른 프레임웍과 틀립니다.
사용자 이벤트를 사용하기 위해서 namespace에 event name을 등록해야 된다는 것인데요.

  'namespace:eventname' 이 처럼 하면 됩니다.

사용자 이벤트 부분을 담당해서 개발했던 Sam은 사용자 이벤트를 이렇게 사용해야 된다는 것에 이처럼 말했습니다.
  
  " 작지만 중요한 변화는 사용자 이벤트를 만들어졌다.[7835] : 모든 사용자 이벤트 명은 namespace에 등록되어야 합니다.  이것은 Prototype.js 만의 솔루션이고 "mousewheel" 과 "DOMMouseScroll" 처럼 비표준 네이티브 DOM 이벤트이기 때문에 사용자 이벤트 네임의 충돌문제를 해결하기 위함입니다. "

$('pandora').observe('PTV:play', function(event) {
   alert(event.memo);
  });
이 예제는 'PTV' namespace에 있는 'play' 이벤트를 실행하는 방법입니다.


Prototype Custom Event 중 한가지

Prototype 1.6.0 정식 버젼에서는  'dom:loaded' 이벤트를 가지고 있습니다.
window 오브젝트에 의해서 이 이벤트는 실행되는데요. 이 이벤트는 DOM tree 즉 document가 모두 load 되고 나면 실행되게 됩니다. document가 모두 load되었다는 것은 쉽게는 html 문서가 다운로드 됨을 의미합니다.

그안에 내포된 image 리소스까지 모두 다운로드 됨을 의미하는것은 아닙니다.

우리가 브라우저를 통해 원격지의 어떤 URL을 요청하게 되면 그 URL의 HTML 문서 즉 document 객체가 모두 다운로드 다운로드되고 DOM에 의해서 랜더링 과정을 거치면서 거기에 해당되는 js, css, img 들을 요청합니다.
이래서 HTTP Request 가 계속 발생하게 됩니다.

이런 과정이 많을 수록 웹 페이지의 포퍼먼스는 떨어지게 됩니다.
본론으로 들어가서요. document 가 onload가 되면 'dom' namespace의 loaded 사용자 이벤트가 발생하게 되어있습니다.



제가 생각할때 이 사용자 이벤트는 상당히 고급 Web App를 개발하는데 큰 도움이 됩니다.
IE에서는 fireEvent 가 내부적으로 지원을 하고 있습니다. 하지만 FF, Opera, Safari에서는 자체적 지원은 되지 않고 DOM 메서드를 통해서 어렵게(?) 구현을 해야합니다.

간지러운 부분을 Prototype에서 이번에 잘 긁어 주었네요.
신고
Posted by Rhio.kim
Prototype.js 완전 정복 필자이신 김영보님께서 로드맵을 만드셨네요.

사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
신고
Posted by Rhio.kim

--prototype.js-------------------------------------------------------------------------

var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

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

Utility Methods 에는 편리한 Method이 아주 많이 정의 되어있습니다.  

실제로 DHTML 컨트롤을 위하여 유용한 '$'  쉽게 $('ID of Element') 하게되면 HtmlElement 가 반환됩니다.

function foo(element) {     
	element = $(element);     /* rest of the function... */ 
} 
'$' 기능은 Element.extend를 가지고 반환된 모든 엘리먼트를 확장할 수 있어서 Prototype의 DOM 확장을 
이용할 수 있다.

아래의 소스를 보면 두 줄이 있는데 비슷하지만 두번째 것이 좀더 객체지향적인 느낌을 준다.

// Note quite OOP-like... 
Element.hide('itemId'); 
// A cleaner feel, thanks to guaranted extension 
$('itemId').hide(); 

그러나 반복 실행이나 레버레이징을 이용할때 '$' 기능은 좀더 우와하고 좀더 간결하고 또한 좀더 효율적인 
코드는 아니다.

['item1', 'item2', 'item3'].each(Element.hide); 
// The better way: 
$('item1', 'item2', 'item3').invoke('hide'); 


단 주의해야할 것은 많은 엘리먼트에 동일 ID를 할당하면 문제를 발생한다는 것. (당근 빠따 ^-^*)


그리고 '$$' Utility 

$$('div'); 
// -> all DIVs in the document. Same as document.getElementsByTagName('div')! 
$$('#contents'); 
// -> same as $('contents'), only it returns an array anyway. 
$$('li.faux'); 
// -> all LI elements with class 'faux'  

이 유틸은 document 전체를 검색합니다.  document의 좀더 정확하고 빠르게 섹션을 찾기위해 내부적으로 
Element.getElementsBySelector를 이용한다.

또한 CSS 구문까지 지원을 한답니다. 브라우저 내부적인 CSS 파싱 처리능력에 의존하지(그렇지 않고는, 
크로스브라우저 문제 갖는다) 않으므로 일관된 선별자('$$' 기능내의 Method)들이 모든 브라우저도 
제공되어진다.

$$('#contents a[rel]'); 
// -> 모든 a태그를  "contents" 라는 아이디를 갖는 엘리먼트 with a rel attribute 
$$('a[href="#"]'); 
// -> all links with a href attribute of value "#" (eyeew!) 
$$('#navbar a', '#sidebar a'); 
// -> all links within the elements of ID "navbar" or "sidebar"
		

$A(iterable) -> actualArray

$A()의 주요 기능은 배열로 만들 수 있는 오브젝트화된 무엇이든 실제 배열로 얻기 위한 것이다.

var paras = $A(document.getElementsByTagName('p')); 
//paras 에 document에 있는 p 태그를 배열 오브젝트로 담습니다.
paras.each(Element.hide); 
//paras.each(이터레이터) 즉 paras의 배열 오브젝트 즉 배열에 담긴 엘리먼트들 중에서 display가 
//none 다시 말해서 표시되지 않고 있는 엘리먼트가 있는지 체크하고
$(paras.last()).show(); 
//paras에 담겨있는 엘리먼트중 마지막 엘리먼트를 표시합니다.

여기에서 paras.each(Element.hide)를 한 이유는 $A() 로 얻어진 배열 오브젝트의 각 엘리먼트들은 
확장된 엘리먼트가 아닙니다.
쉽게 순수한 엘리먼트 오브젝트들만 담겨 있어.. 3번째 수행문인 paras.last() 의 last() 메서드나 , 
show() 메서드를 수행할 수는 없습니다. 하지만 each 함수가 수행되면서 확장되기 때문에 그냥 사용할 수 
있게된다.

$F(element) -> value

$F() 함수는 아규먼트로한 지정한 엘리먼트에 입력한 값을 추출하는 축약함수


$H([obj]) -> Hash

$H() 함수는 아규먼트에 지정한 오브젝트로 Hash 오브젝트를 생성한다.  만약 Object 속성이 Hash이면
받은 파라미터를 반환하고 종료한다.

--prototype.js------------------------------------------------------------------------
var Hash = function(object) {
  if (object instanceof Hash) this.merge(object);
  else Object.extend(this, object || {});
};

function $H(object) {
  if (object instanceof Hash) return object;
  return new Hash(object);
};
--------------------------------------------------------------------------------------
		

$R(start, end[, exclusive = false]) -> ObjectRange

$R() 메서드는 ObjectRange 인스턴스는 연속되는 값의 범위를 표현한다. 숫자형, 문자형 혹은 의미적인 
값의 범위가 있는 다른 타입도 제공합니다. 예를 들어 한글도 지원한다는 좀더 자세히 알려면 타입형의 
문서를 보고 여러분만의 오브젝트가 제공할 수 있는 값의 범위를 발견해볼 것

$R 기능은 ObjectRange을 생성해서 바로 리턴하는 역활을 합니다. 아규먼트로 start, end, exclusive
를 받는데 이 값들은 ObjectRange Class 에 전달되면서 Enumerable를 상속(확장) 

삼천포 : Prototype.js 에서는 도대체 상속과 확장의 개념이 잘 정리가 안됩니다. 상속은 부모 클래스에서 
자식 클래스로 무언가 상속받다는 개념이 되야하는데 Javascript 자체는 OOP가 아니고 OOP like이고 또한 
ObjectRang와 Enumerable 어느것이 부모 Class가 아니기 때문에 상속이란 개념보다는 ObjectRang의 
기능을 확장 즉 Object가 Extend가 되는게 맞는데 또 누구는 상속이라 하기도 합니다. 암튼 그렇고 다시 ..

ObjectRang은 Enumerable의 기능을 

--prototype.js---------------------------------------------------------------------------ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}
----------------------------------------------------------------------------------------

--example-------------------------------------------------------------------------------
$R(0, 10).include(10) 
// -> true 
$A($R(0, 5)).join(', ') 
// -> '0, 1, 2, 3, 4, 5' 
$A($R('aa', 'ah')).join(', ') 
// -> 'aa, ab, ac, ad, ae, af, ag, ah' 
$R(0, 10, true).include(10) 
// -> false 
$A($R('가','갸'))
// -> 가,각,갂,갃,간,갅,갆,갇,갈,갉,갊,갋,갌,갍,갎,갏,감,갑,값,갓,갔,강,갖,갗,갘,같,갚,
갛,개,객,갞,갟,갠,갡,갢,갣,갤,갥,갦,갧,갨,갩,갪,갫,갬,갭,갮,갯,갰,갱,갲,갳,갴,갵,갶,갷,갸
$R(0, 10, true).each(function(value) {   
// invoked 10 times for value = 0 to 9 
}); 
----------------------------------------------------------------------------------------
	
신고
Posted by Rhio.kim

Prototype takes issue with only one aspect of functions: binding.
Prototype은 기능의 관점에서 유일하게 갖고 있는게 'binding' 이다.

“Binding” basically determines the meaning, when a function runs, of the this keyword. 
While there usually is a proper default binding 
(this refers to whichever object the method is called on), 
this can be “lost” sometimes, for instance when passing a function reference as an argument.

Binding 이란 함수가 실행될때 this 객체를 결정하는 방법입니다. 
예를 들어 아규먼트로 함수 레퍼런스(참조변수)를 넘길때 때때로 "lost" 될 수 있어 이런일이 
발생하는 동안에 고유의 기본 바인딩 기능이 있다.
(this는 Method가 요청된 어떤 오브젝트든지 참조할 수 있다)


If you don’t know much about the this keyword in JavaScript, hop to the docs for the bind() 
method. 
The examples there will clear it up.

만약에 여러분이 javascript에서 this객체에 관해서 잘 모른다면 bind()에 대한건 넘어가세요.


--prototype.js--------------------------------------------------------------

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

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));
  }
}



--for example--------------------------------------------------------------

window.name = "www.pandora.tv";

Function Test() {
  return this.name;
}
Test(); //-> 'www.pandora.tv'

var foo = {
  name : 'www.google.com',
  otherTest : function() { return this.name }
}

foo.otherTest(); //-> 'www.google.com'

Function runFx(f) { f(); }

var fx = foo.otherTest.bind(foo);

runFx(foo.otherTest); //->
runFx(fx); //->
		
신고
Posted by Rhio.kim

***** XMLHttpRequest의 메서드

Ajax
	var Ajax = {
	  getTransport: function() {
	    return Try.these(
	      function() {return new XMLHttpRequest()},
	      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
	      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
	    ) || false;
	  },
	
	  activeRequestCount: 0
	}
	
	● Ajax.Base
		Ajax.Base = function() {};
		Ajax.Base.prototype = {
		  setOptions: function(options) {
		    this.options = {
		      method:       'post',
		      asynchronous: true,
		      contentType:  'application/x-www-form-urlencoded',
		      encoding:     'UTF-8',
		      parameters:   ''
		    }
		    Object.extend(this.options, options || {});
		
		    this.options.method = this.options.method.toLowerCase();
		    if (typeof this.options.parameters == 'string')
		      this.options.parameters = this.options.parameters.toQueryParams();
		  }
		}
		
	● Ajax.Options
	   이 클래스는 모든 AJAX 요청에 의해 공개된 모든 중요 옵션과 콜백을 세부적으로 갖는다.
		
	● Ajax.PeriodicalUpdater : new Ajax.PeriodicalUpdater(container, url[, options])
	   주기적으로 AJAX 요청과 response text 바탕으로된 컨텐츠 갱신을 수행한다. 
		
	● Ajax.Request : new Ajax.Request(url[, options])
	   AJAX 요청 시작과 수행
		
	● Ajax.Responders : 
            Ajax.Responders.register(responder), Ajax.Responders.unregister(responder)
	   전역 리스너의 저장소는 Prototype-based AJAX요청의 모든 단계에 대해 통보(변화)한다.
		
	● Ajax.Updater
		

	
var UI = Class.create();
UI.prototype = {
  AX : null,
  initialize : null,
  getHTML : function() {
  },
  recv : function() {
  },
}

var oUI = new UI();

간단한 UI 객체의 구조입니다. 

UI class를 만들었습니다. 그러면 getHTML(ajax를 통해 HTML 소스 즉 서버측에 요구하는 값을 
받아오는 Method)와 recv (ajax를 통해 결과를 받아 파싱하는 Method)를 보겠습니다.

getHTML : function() {
  var url = '/ajax.php';

  this.AX = new Ajax.Request(url, {
    method : 'get',  // basic set is POST
	parameters : { 'file' : 'index.htm' },
    onSuccess : function(result) {
       this.recv(result);
    }.bind(this),
    onFailure : function() {
       alert('HTML을 받아오지 못했습니다.');
    }
  })
}

위의 getHTML Method를 보면 new Ajax가 생성되고 url과 JSON이 파라메터로 넘어갑니다.
url, { method : 'get' , parameters : { 'file' : 'index.htm' }, onSuccess : '' , onFailure : '' } 
이렇게 두가지의 파라미터가 넘어갑니다.

ajax는 이 JSON을 받아서 내부적으로 처리합니다. 그 결과에 따라 성공하면 onSuccess에 
처리문을 수행합니다.

여기엔 다양한 Method가 있습니다. 기본적으로 onComplete, onSuccess, onFailure 등이 있습니다.

위에서 
onSuccess : function(result) {
  this.recv(result);
}.bind(this),

이 부분은 성공시에 처리되는 것이며 function() {}.bind(this) 에서 bind(this)는 
anonymous function 을 호출시에 발생하는 this 객체 즉 anonymous function를 호출한 객체를 
익명함수 내부에서도 사용할 수 있도록 bind(Oject instance name) 를 사용함으로 
Object instance name 을 익명함 수 내에서도 사용할 수 있게 됩니다.

onSuccess는 Ajax객체의 내무 Method이므로 Ajax 객체 내에서 사용하는 this.recv(result)는 
.bind() 가 없을 경우 this.recv(result)의 this는 Ajax를 가리키게 되지만 .bind함수는 
이를 해결하기 위한 Prototype의 기능입니다.


만약 Ajax객체가 성공적으로 수행하여 결과가 정상적으로 리턴되었다면 this.recv(result)는 
실행될 것이며 UI 객체에 있는 recv Method가 수행될것입니다.

  recv : function(XHR) {
     alert(XHR.responseText);
  },

는 실제 XMLHTTPRequest에 의해 return된 오브젝트이며 프로퍼티중 responseText 에 결과가 
담겨져 있습니다.
XHR.responseText를 alert으로 출력해보면 결과에 맞는 내용이 string으로 뿌려지게 됩니다.

아주 간단한 prototype을 이용한 ajax통신을 보았구요. 예제를 통한 설명이 이쯤에서 끝냅니다.

Prototype내의 Ajax Object를 살펴 보시면 다양한 Method와 하위 Object들 볼 수 있습니다.
Ajax부분에 고급화된 Object와 Method를 제공하고 있고 위에서 보여드린 부분은 아주 간단한 
Ajax를 이용한 호출과 결과값을 보여주는 부분입니다.

강좌는 계속 이어지구요. 질문 사항은 이곳 게시판이나 메일로 보내주시면..
서로 공부해서 ^^
설명중 Class, 오브젝트, 객체는 모두 같은 의미를 갖으며 설명중 중복이 싫어서 자꾸 바뀌는 
경향이 있으니 이점 생각하시고 보세요. 
		
신고
Posted by Rhio.kim
사용자 삽입 이미지

요런 페이지 네비게이터를 만들어 줍니다.
Prototype.js 가 필요하구요.

소스와 예제는 첨부합니다.



var navi = new Navigator(this, { target : 'result', lang : 'ko', callback : this.doMove, total : 110, limit : 10, pageSize : 5, currPage : 1 } );
navi.show(); //diplay
navi.go(3); //goto page

navi.reset({ target : 'result', lang : 'ko', callback : this.doMove, total : 110, limit : 10, pageSize : 5, currPage : 1 }); //page options reset

●options description●
this.options = { target : 'result', lang : 'ko', callback : this.doMove, total : 110, limit : 10, pageSize : 5, currPage : 1 }
target 뿌려질 엘리먼트 아이디
lang 사용될 언어 리소스
callback 네비게이터 클릭했을때 사용될 콜백 함수
total 레코드 총 개수
limit 페이지당 표시될 레코드
pageSize 한 화면에 뿌려질 페이지 개수
currPage 초기화 페이지

●property description●
navi.options.currPage 는 현재 선택된 페이지 번호
navi.options.target 는 표시될 엘리먼트 아이디
navi._totPage 는 토탈 페이지
신고
Posted by Rhio.kim
우선 모든 강좌는 간단하고 Core만 다루도록 하겠습니다.
Prototype 이라는 Open Framework 이기 때문에 찾아서 혹은 직접 해보면서 다양한 기능을 다룰 수 있을것 입니다.

또한 객체 지향적인 개발 방법으로만 다루겠습니다.
Framework을 이용하는 이유 역시 간단한 함수 호출을 위해서 만든 오픈 라이브러리가 아니기 때문입니다.

var UI = Class.create();
UI.prototype = {
  AX : null,
  initialize : null,
  getHTML : function() {
  },
  recv : function() {
  },
}

var oUI = new UI();

간단한 UI 객체의 구조입니다.

UI class를 만들었습니다. 그러면 getHTML(ajax를 통해 HTML 소스 즉 서버측에 요구하는 값을 받아오는 Method)와 recv (ajax를 통해 결과를 받아 파싱하는 Method)를 보겠습니다.

getHTML : function() {
  var url = '/ajax.php';

  this.AX = new Ajax(url, {
    method : 'get',  // basic set is POST
    parameters : { 'file' : 'index.htm' },
    onSuccess : function(result) {
       this.recv(result);
    }.bind(this),
    onFailure : function() {
       alert('HTML을 받아오지 못했습니다.');
    }
  })
}

위의 getHTML Method를 보면 new Ajax가 생성되고 url과 JSON이 파라메터로 넘어갑니다.
url, { method : 'get' , parameters : { 'file' : 'index.htm' }, onSuccess : '' , onFailure : '' }
이렇게 두가지의 파라미터가 넘어갑니다.

ajax는 이 JSON을 받아서 내부적으로 처리합니다. 그 결과에 따라 성공하면 onSuccess에 처리문을 수행합니다.

여기엔 다양한 Method가 있습니다. 기본적으로 onComplete, onSuccess, onFailure 등이 있습니다.

위에서
onSuccess : function(result) {
  this.recv(result);
}.
bind(this),

이 부분은 성공시에 처리되는 것이며 function() {}.bind(this) 에서 bind(this)
anonymous function 을 호출시에 발생하는 this 객체 즉 anonymous function를 호출한 객체 를 익명함수 내부에서도 사용할 수 있도록 bind(Oject instance name) 를 사용함으로 Object instance name 을 익명함 수 내에서도 사용할 수 있게 됩니다.

onSuccess는 Ajax객체의 내무 Method이므로 Ajax 객체 내에서 사용하는 this.recv(result)는 .bind() 가 없을 경우 this.recv(result)의 this는 Ajax를 가리키게 되지만 .bind함수는 이를 해결하기 위한 Prototype의 기능입니다.


만약 Ajax객체가 성공적으로 수행하여 결과가 정상적으로 리턴되었다면 this.recv(result)는 실행될 것이며 UI 객체에 있는 recv Method가 수행될것입니다.

  recv : function(XHR) {
     alert(XHR.responseText);
  },

는 실제 XMLHTTPRequest에 의해 return된 오브젝트이며 프로퍼티중 responseText 에 결과가 담겨져 있습니다.
XHR.responseText를 alert으로 출력해보면 결과에 맞는 내용이 string으로 뿌려지게 됩니다.

아주 간단한 prototype을 이용한 ajax통신을 보았구요. 예제를 통한 설명이 이쯤에서 끝냅니다.

Prototype내의 Ajax Object를 살펴 보시면 다양한 Method와 하위 Object들 볼 수 있습니다.
Ajax부분에 고급화된 Object와 Method를 제공하고 있고 위에서 보여드린 부분은 아주 간단한 Ajax를 이용한
호출과 결과값을 보여주는 부분입니다.

강좌는 계속 이어지구요. 질문 사항은 이곳 게시판이나 메일로 보내주시면..
서로 공부해서 ^^
설명중 Class, 오브젝트, 객체는 모두 같은 의미를 갖으며 설명중 중복이 싫어서 자꾸 바뀌는 경향이 있으니
이점 생각하시고 보세요.
신고
Posted by Rhio.kim


티스토리 툴바