日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【转】一个优秀的Javascript框架--Prototype解说

發布時間:2024/8/5 java 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】一个优秀的Javascript框架--Prototype解说 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

from:http://blog.csdn.net/meil/archive/2007/04/25/1585056.aspx
????? Prototype.js 是Ruby On Rails的副產品, Javascript編寫者的一把小軍刀,提供了Ruby風格的簡寫語法和實效的函數,更難得的是完全跨瀏覽器,讓大家舒舒服服寫出又精簡又不用愁心兼容的的JS代碼,SpringSide 已經離不開它了。

Prototype在線手冊

/**?
?*?定義一個全局對象,?屬性?Version?在發布的時候會替換為當前版本號?
?
*/?
var?Prototype?=?{?
??Version:?'@@VERSION@@'?
}?

/**?
?*?創建一種類型,注意其屬性?create?是一個方法,返回一個構造函數。?
?*?一般使用如下??
?*?????var?X?=?Class.create();??返回一個類型,類似于?java?的一個Class實例。?
?*?要使用?X?類型,需繼續用?new?X()來獲取一個實例,如同?java?的?Class.newInstance()方法。?
?*?
?*?返回的構造函數會執行名為?initialize?的方法,?initialize?是?Ruby?對象的構造器方法名字。?
?*?此時initialize方法還沒有定義,其后的代碼中創建新類型時會建立相應的同名方法。?
?*?
?*?如果一定要從java上去理解。你可以理解為用Class.create()創建一個繼承java.lang.Class類的類。當然java不允許這樣做,因為Class類是final的?
?*?
?
*/?
var?Class?=?{?
??create:?
function()?{?
????
return?function()?{?
??????
this.initialize.apply(this,?arguments);?
????}?
??}?
}?

/**?
?*?創建一個對象,從變量名來思考,本意也許是定義一個抽象類,以后創建新對象都?extend?它。?
?*?但從其后代碼的應用來看,?Abstract?更多是為了保持命名空間清晰的考慮。?
?*?也就是說,我們可以給?Abstract?這個對象實例添加新的對象定義。?
?*?
?*?從java去理解,就是動態給一個對象創建內部類。?
?
*/?
var?Abstract?=?new?Object();?

/**?
?*?獲取參數對象的所有屬性和方法,有點象多重繼承。但是這種繼承是動態獲得的。?
?*?如:?
?*?????var?a?=?new?ObjectA(),?b?=?new?ObjectB();?
?*?????var?c?=?a.extend(b);?
?*?此時?c?對象同時擁有?a?和?b?對象的屬性和方法。但是與多重繼承不同的是,c?instanceof?ObjectB?將返回false。?
?
*/?
Object.prototype.extend?
=?function(object)?{?
??
for?(property?in?object)?{?
????
this[property]?=?object[property];?
??}?
??
return?this;?
}?

/**?
?*?這個方法很有趣,它封裝一個javascript函數對象,返回一個新函數對象,新函數對象的主體和原對象相同,但是bind()方法參數將被用作當前對象的對象。?
?*?也就是說新函數中的?this?引用被改變為參數提供的對象。?
?*?比如:?
?*?????<input?type="text"?id="aaa"?value="aaa">?
?*?????<input?type="text"?id="bbb"?value="bbb">?
?*?????..?
?*?????<script>?
?*?????????var?aaa?=?document.getElementById("aaa");?
?*?????????var?bbb?=?document.getElementById("bbb");?
?*?????????aaa.showValue?=?function()?{alert(this.value);}?
?*?????????aaa.showValue2?=?aaa.showValue.bind(bbb);?
?*?????</script>?
?*??那么,調用aaa.showValue?將返回"aaa",?但調用aaa.showValue2?將返回"bbb"。?
?*?
?*?apply?是ie5.5后才出現的新方法(Netscape好像很早就支持了)。?
?*?該方法更多的資料參考MSDN?http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthApply.asp?
?*?還有一個?call?方法,應用起來和?apply?類似??梢砸黄鹧芯肯?。?
?
*/?
Function.prototype.bind?
=?function(object)?{?
??
var?method?=?this;?
??
return?function()?{?
????method.apply(object,?arguments);?
??}?
}?

/**?
?*?和bind一樣,不過這個方法一般用做html控件對象的事件處理。所以要傳遞event對象?
?*?注意這時候,用到了?Function.call。它與?Function.apply?的不同好像僅僅是對參數形式的定義。?
?*?如同?java?兩個過載的方法。?
?
*/?
Function.prototype.bindAsEventListener?
=?function(object)?{?
??
var?method?=?this;?
??
return?function(event)?{?
????method.call(object,?event?
||?window.event);?
??}?
}?

/**?
?*?將整數形式RGB顏色值轉換為HEX形式?
?
*/?
Number.prototype.toColorPart?
=?function()?{?
??
var?digits?=?this.toString(16);?
??
if?(this?<?16)?return?'0'?+?digits;?
??
return?digits;?
}?

/**?
?*?典型?Ruby?風格的函數,將參數中的方法逐個調用,返回第一個成功執行的方法的返回值?
?
*/?
var?Try?=?{?
??these:?
function()?{?
????
var?returnValue;?
????
????
for?(var?i?=?0;?i?<?arguments.length;?i++)?{?
??????
var?lambda?=?arguments[i];?
??????
try?{?
????????returnValue?
=?lambda();?
????????
break;?
??????}?
catch?(e)?{}?
????}?
????
????
return?returnValue;?
??}?
}?

/*--------------------------------------------------------------------------*/?

/**?
?*?一個設計精巧的定時執行器?
?*?首先由?Class.create()?創建一個?PeriodicalExecuter?類型,?
?*?然后用對象直接量的語法形式設置原型。?
?*?
?*?需要特別說明的是?rgisterCallback?方法,它調用上面定義的函數原型方法bind,?并傳遞自己為參數。?
?*?之所以這樣做,是因為?setTimeout?默認總以?window?對象為當前對象,也就是說,如果?registerCallback?方法定義如下的話:?
?*?????registerCallback:?function()?{?
?*?????????setTimeout(this.onTimerEvent,?this.frequency?*?1000);?
?*?????}?
?*?那么,this.onTimeoutEvent?方法執行失敗,因為它無法訪問?this.currentlyExecuting?屬性。?
?*?而使用了bind以后,該方法才能正確的找到this,也就是PeriodicalExecuter的當前實例。?
?
*/?
var?PeriodicalExecuter?=?Class.create();?
PeriodicalExecuter.prototype?
=?{?
??initialize:?
function(callback,?frequency)?{?
????
this.callback?=?callback;?
????
this.frequency?=?frequency;?
????
this.currentlyExecuting?=?false;?
????
????
this.registerCallback();?
??},?
??
??registerCallback:?
function()?{?
????setTimeout(
this.onTimerEvent.bind(this),?this.frequency?*?1000);?
??},?
??
??onTimerEvent:?
function()?{?
????
if?(!this.currentlyExecuting)?{?
??????
try?{?
????????
this.currentlyExecuting?=?true;?
????????
this.callback();?
??????}?
finally?{?
????????
this.currentlyExecuting?=?false;?
??????}?
????}?
????
????
this.registerCallback();?
??}?
}?

/*--------------------------------------------------------------------------*/?

/**?
?*?這個函數就?Ruby?了。我覺得它的作用主要有兩個?
?*?1.??大概是?document.getElementById(id)?的最簡化調用。?
?*?比如:$("aaa")?將返回上?aaa?對象?
?*?2.??得到對象數組?
?*?比如:?$("aaa","bbb")?返回一個包括id為"aaa"和"bbb"兩個input控件對象的數組。?
?
*/?
function?$()?{?
??
var?elements?=?new?Array();?
??
??
for?(var?i?=?0;?i?<?arguments.length;?i++)?{?
????
var?element?=?arguments[i];?
????
if?(typeof?element?==?'string')?
??????element?
=?document.getElementById(element);?

????
if?(arguments.length?==?1)?
??????
return?element;?
??????
????elements.push(element);?
??}?
??
??
return?elements;?
}?

?

/**?
?*?定義?Ajax?對象,?靜態方法?getTransport?方法返回一個?XMLHttp?對象?
?
*/?
var?Ajax?=?{?
??getTransport:?
function()?{?
????
return?Try.these(?
??????
function()?{return?new?ActiveXObject('Msxml2.XMLHTTP')},?
??????
function()?{return?new?ActiveXObject('Microsoft.XMLHTTP')},?
??????
function()?{return?new?XMLHttpRequest()}?
????)?
||?false;?
??},?
??
??emptyFunction:?
function()?{}?
}?

/**?
?*?我以為此時的Ajax對象起到命名空間的作用。?
?*?Ajax.Base?聲明為一個基礎對象類型?
?*?注意?Ajax.Base?并沒有使用?Class.create()?的方式來創建,我想是因為作者并不希望?Ajax.Base?被庫使用者實例化。?
?*?作者在其他對象類型的聲明中,將會繼承于它。?
?*?就好像?java?中的私有抽象類?
?
*/?
Ajax.Base?
=?function()?{};?
Ajax.Base.prototype?
=?{?
??
/**?
???*?extend?(見prototype.js中的定義)?的用法真是讓人耳目一新?
???*?options?首先設置默認屬性,然后再?extend?參數對象,那么參數對象中也有同名的屬性,那么就覆蓋默認屬性值。?
???*?想想如果我寫這樣的實現,應該類似如下:?
?????setOptions:?function(options)?{?
??????this.options.methed?=?options.methed??options.methed?:?'post';?
??????.?
?????}?
?????我想很多時候,java?限制了?js?的創意。?
???
*/?
??setOptions:?
function(options)?{?
????
this.options?=?{?
??????method:???????'post',?
??????asynchronous:?
true,?
??????parameters:???''?
????}.extend(options?
||?{});?
??}?
}?


/**?
?*?Ajax.Request?封裝?XmlHttp?
?
*/?
Ajax.Request?
=?Class.create();?

/**?
?*?定義四種事件(狀態),?參考http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/readystate_1.asp?
?
*/?
Ajax.Request.Events?
=?
??['Uninitialized',?'Loading',?'Loaded',?'Interactive',?'Complete'];?

/**?
?*?
?
*/?
Ajax.Request.prototype?
=?(new?Ajax.Base()).extend({?
??initialize:?
function(url,?options)?{?
????
this.transport?=?Ajax.getTransport();?
????
this.setOptions(options);?
??
????
try?{?
??????
if?(this.options.method?==?'get')?
????????url?
+=?'?'?+?this.options.parameters?+?'&_=';?
????
?????
/**?
??????*?此處好像強制使用了異步方式,而不是依照?this.options.asynchronous?的值?
??????
*/?
??????
this.transport.open(this.options.method,?url,?true);?
??????
?????
/**?
??????*?這里提供了?XmlHttp?傳輸過程中每個步驟的回調函數?
??????
*/?
??????
if?(this.options.asynchronous)?{?
????????
this.transport.onreadystatechange?=?this.onStateChange.bind(this);?
????????setTimeout((
function()?{this.respondToReadyState(1)}).bind(this),?10);?
??????}?
??????????????
??????
this.transport.setRequestHeader('X-Requested-With',?'XMLHttpRequest');?
??????
this.transport.setRequestHeader('X-Prototype-Version',?Prototype.Version);?

??????
if?(this.options.method?==?'post')?{?
????????
this.transport.setRequestHeader('Connection',?'close');?
????????
this.transport.setRequestHeader('Content-type',?
??????????'application
/x-www-form-urlencoded');?
??????}?
??????
??????
this.transport.send(this.options.method?==?'post'???
????????
this.options.parameters?+?'&_='?:?null);?
??????????????????????
????}?
catch?(e)?{?
????}????
??},?
??????
??onStateChange:?
function()?{?
????
var?readyState?=?this.transport.readyState;?
???
/**?
????*?如果不是?Loading?狀態,就調用回調函數?
?????
*/?
????
if?(readyState?!=?1)?
??????
this.respondToReadyState(this.transport.readyState);?
??},?
??
??
/**?
???*?回調函數定義在?this.options?屬性中,比如:?
??????var?option?=?{?
?????????onLoaded?:?function(req)?{};?
??????????
??????}?
??????new?Ajax.Request(url,?option);?
???
*/?
??respondToReadyState:?
function(readyState)?{?
????
var?event?=?Ajax.Request.Events[readyState];?
????(
this.options['on'?+?event]?||?Ajax.emptyFunction)(this.transport);?
??}?
});?

/**?
?*?Ajax.Updater?用于綁定一個html元素與?XmlHttp調用的返回值。類似與?buffalo?的?bind。?
?*?如果?options?中有?insertion(from?dom.js)?對象的話,?insertion?能提供更多的插入控制。?
?
*/?
Ajax.Updater?
=?Class.create();?
Ajax.Updater.prototype?
=?(new?Ajax.Base()).extend({?
??initialize:?
function(container,?url,?options)?{?
????
this.container?=?$(container);?
????
this.setOptions(options);?
??
????
if?(this.options.asynchronous)?{?
??????
this.onComplete?=?this.options.onComplete;?
??????
this.options.onComplete?=?this.updateContent.bind(this);?
????}?
????
????
this.request?=?new?Ajax.Request(url,?this.options);?
????
????
if?(!this.options.asynchronous)?
??????
this.updateContent();?
??},?
??
??updateContent:?
function()?{?
????
if?(this.options.insertion)?{?
??????
new?this.options.insertion(this.container,?
????????
this.request.transport.responseText);?
????}?
else?{?
??????
this.container.innerHTML?=?this.request.transport.responseText;?
????}?

????
if?(this.onComplete)?{?
??????setTimeout((
function()?{this.onComplete(this.request)}).bind(this),?10);?
????}?
??}?
});?

?

/**?
?*?針對?頁面元素對象?的工具類,提供一些簡單靜態方法?
?
*/?
var?Field?=?{?
??
/**?
???*?清除參數引用對象的值?
???
*/?
??clear:?
function()?{?
????
for?(var?i?=?0;?i?<?arguments.length;?i++)?
??????$(arguments[i]).value?
=?'';?
??},?

??
/**?
???*?使參數引用對象獲取焦點?
???
*/?
??focus:?
function(element)?{?
????$(element).focus();?
??},?
??
??
/**?
???*?判斷參數引用對象值是否為空,如為空,返回false,?反之true?
???
*/?
??present:?
function()?{?
????
for?(var?i?=?0;?i?<?arguments.length;?i++)?
??????
if?($(arguments[i]).value?==?'')?return?false;?
????
return?true;?
??},?
??
??
/**?
???*?使選中參數引用對象?
???
*/?
??select:?
function(element)?{?
????$(element).select();?
??},?

??
/**?
???*?使參數引用對象處于可編輯狀態?
???
*/?
??activate:?
function(element)?{?
????$(element).focus();?
????$(element).select();?
??}?
}?

/*--------------------------------------------------------------------------*/?

/**?
?*?表單工具類?
?
*/?
var?Form?=?{?
??
/**?
???*?將表單元素序列化后的值組合成?QueryString?的形式?
???
*/?
??serialize:?
function(form)?{?
????
var?elements?=?Form.getElements($(form));?
????
var?queryComponents?=?new?Array();?
????
????
for?(var?i?=?0;?i?<?elements.length;?i++)?{?
??????
var?queryComponent?=?Form.Element.serialize(elements[i]);?
??????
if?(queryComponent)?
????????queryComponents.push(queryComponent);?
????}?
????
????
return?queryComponents.join('&');?
??},?
??
??
/**?
???*?得到表單的所有元素對象?
???
*/?
??getElements:?
function(form)?{?
????form?
=?$(form);?
????
var?elements?=?new?Array();?

????
for?(tagName?in?Form.Element.Serializers)?{?
??????
var?tagElements?=?form.getElementsByTagName(tagName);?
??????
for?(var?j?=?0;?j?<?tagElements.length;?j++)?
????????elements.push(tagElements[j]);?
????}?
????
return?elements;?
??},?
??
??
/**?
???*?將指定表單的元素置于不可用狀態?
???
*/?
??disable:?
function(form)?{?
????
var?elements?=?Form.getElements(form);?
????
for?(var?i?=?0;?i?<?elements.length;?i++)?{?
??????
var?element?=?elements[i];?
??????element.blur();?
??????element.disable?
=?'true';?
????}?
??},?

??
/**?
???*?使表單的第一個非?hidden?類型而且處于可用狀態的元素獲得焦點?
???
*/?
??focusFirstElement:?
function(form)?{?
????form?
=?$(form);?
????
var?elements?=?Form.getElements(form);?
????
for?(var?i?=?0;?i?<?elements.length;?i++)?{?
??????
var?element?=?elements[i];?
??????
if?(element.type?!=?'hidden'?&&?!element.disabled)?{?
????????Field.activate(element);?
????????
break;?
??????}?
????}?
??},?

??
/*?
???*?重置表單?
???
*/?
??reset:?
function(form)?{?
????$(form).reset();?
??}?
}?

/**?
?*?表單元素工具類?
?
*/?
Form.Element?
=?{?
??
/**?
???*?返回表單元素的值先序列化再進行?URL?編碼后的值?
???
*/?
??serialize:?
function(element)?{?
????element?
=?$(element);?
????
var?method?=?element.tagName.toLowerCase();?
????
var?parameter?=?Form.Element.Serializers[method](element);?
????
????
if?(parameter)?
??????
return?encodeURIComponent(parameter[0])?+?'='?+?
????????encodeURIComponent(parameter[
1]);????????????????????
??},?
??
??
/**?
???*??返回表單元素序列化后的值?
???
*/?
??getValue:?
function(element)?{?
????element?
=?$(element);?
????
var?method?=?element.tagName.toLowerCase();?
????
var?parameter?=?Form.Element.Serializers[method](element);?
????
????
if?(parameter)?
??????
return?parameter[1];?
??}?
}?

/**?
?*?prototype?的所謂序列化其實就是將表單的名字和值組合成一個數組?
?
*/?
Form.Element.Serializers?
=?{?
??input:?
function(element)?{?
????
switch?(element.type.toLowerCase())?{?
??????
case?'hidden':?
??????
case?'password':?
??????
case?'text':?
????????
return?Form.Element.Serializers.textarea(element);?
??????
case?'checkbox':??
??????
case?'radio':?
????????
return?Form.Element.Serializers.inputSelector(element);?
????}?
????
return?false;?
??},?
??
??inputSelector:?
function(element)?{?
????
if?(element.checked)?
??????
return?[element.name,?element.value];?
??},?

??textarea:?
function(element)?{?
????
return?[element.name,?element.value];?
??},?

??
/**?
???*?看樣子,也不支持多選框(select-multiple)?
???
*/?
??select:?
function(element)?{?
????
var?index?=?element.selectedIndex;?
????
var?value?=?element.options[index].value?||?element.options[index].text;?
????
return?[element.name,?(index?>=?0)???value?:?''];?
??}?
}?

/*--------------------------------------------------------------------------*/?

/**?
?*?Form.Element.getValue?也許會經常用到,所以做了一個快捷引用?
?
*/?
var?$F?=?Form.Element.getValue;?

/*--------------------------------------------------------------------------*/?

/**?
?*?Abstract.TimedObserver?也沒有用?Class.create()?來創建,和Ajax.Base?意圖應該一樣?
?*?Abstract.TimedObserver?顧名思義,是套用Observer設計模式來跟蹤指定表單元素,?
?*?當表單元素的值發生變化的時候,就執行回調函數?
?*?
?*?我想 Observer?與注冊onchange事件相似,不同點在于?onchange?事件是在元素失去焦點的時候才激發。?
?*?同樣的與?onpropertychange?事件也相似,不過它只關注表單元素的值的變化,而且提供timeout的控制。?
?*?
?*?除此之外,Observer?的好處大概就在與更面向對象,另外可以動態的更換回調函數,這就比注冊事件要靈活一些。?
?*?Observer?應該可以勝任動態數據校驗,或者多個關聯下拉選項列表的連動等等?
?*?
?
*/?
Abstract.TimedObserver?
=?function()?{}?

/**?
?*?這個設計和?PeriodicalExecuter?一樣,bind?方法是實現的核心?
?
*/?
Abstract.TimedObserver.prototype?
=?{?
??initialize:?
function(element,?frequency,?callback)?{?
????
this.frequency?=?frequency;?
????
this.element???=?$(element);?
????
this.callback??=?callback;?
????
????
this.lastValue?=?this.getValue();?
????
this.registerCallback();?
??},?
??
??registerCallback:?
function()?{?
????setTimeout(
this.onTimerEvent.bind(this),?this.frequency?*?1000);?
??},?
??
??onTimerEvent:?
function()?{?
????
var?value?=?this.getValue();?
????
if?(this.lastValue?!=?value)?{?
??????
this.callback(this.element,?value);?
??????
this.lastValue?=?value;?
????}?
????
????
this.registerCallback();?
??}?
}?

/**?
?*?Form.Element.Observer?和?Form.Observer?其實是一樣的?
?*?注意?Form.Observer?并不是用來跟蹤整個表單的,我想大概只是為了減少書寫(這是Ruby的一個設計原則)?
?
*/?
Form.Element.Observer?
=?Class.create();?
Form.Element.Observer.prototype?
=?(new?Abstract.TimedObserver()).extend({?
??getValue:?
function()?{?
????
return?Form.Element.getValue(this.element);?
??}?
});?

Form.Observer?
=?Class.create();?
Form.Observer.prototype?
=?(new?Abstract.TimedObserver()).extend({?
??getValue:?
function()?{?
????
return?Form.serialize(this.element);?
??}?
});?

?

/**?
?*?根據?class?attribute?的名字得到對象數組,支持?multiple?class?
?*?
?
*/?
document.getElementsByClassName?
=?function(className)?{?
??
var?children?=?document.getElementsByTagName('*')?||?document.all;?
??
var?elements?=?new?Array();?
??
??
for?(var?i?=?0;?i?<?children.length;?i++)?{?
????
var?child?=?children[i];?
????
var?classNames?=?child.className.split('?');?
????
for?(var?j?=?0;?j?<?classNames.length;?j++)?{?
??????
if?(classNames[j]?==?className)?{?
????????elements.push(child);?
????????
break;?
??????}?
????}?
??}?
??
??
return?elements;?
}?

/*--------------------------------------------------------------------------*/?

/**?
?*?Element?就象一個?java?的工具類,主要用來?隱藏/顯示/銷除?對象,以及獲取對象的簡單屬性。?
?*?
?
*/?
var?Element?=?{?
??toggle:?
function()?{?
????
for?(var?i?=?0;?i?<?arguments.length;?i++)?{?
??????
var?element?=?$(arguments[i]);?
??????element.style.display?
=?
????????(element.style.display?
==?'none'???''?:?'none');?
????}?
??},?

??hide:?
function()?{?
????
for?(var?i?=?0;?i?<?arguments.length;?i++)?{?
??????
var?element?=?$(arguments[i]);?
??????element.style.display?
=?'none';?
????}?
??},?

??show:?
function()?{?
????
for?(var?i?=?0;?i?<?arguments.length;?i++)?{?
??????
var?element?=?$(arguments[i]);?
??????element.style.display?
=?'';?
????}?
??},?

??remove:?
function(element)?{?
????element?
=?$(element);?
????element.parentNode.removeChild(element);?
??},?
????
??getHeight:?
function(element)?{?
????element?
=?$(element);?
????
return?element.offsetHeight;?
??}?
}?

/**?
?*?為?Element.toggle?做了一個符號連接,大概是兼容性的考慮?
?
*/?
var?Toggle?=?new?Object();?
Toggle.display?
=?Element.toggle;?

/*--------------------------------------------------------------------------*/?

/**?
?*?動態插入內容的實現,MS的Jscript實現中對象有一個?insertAdjacentHTML?方法(http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertadjacenthtml.asp)?
?*?這里算是一個對象形式的封裝。?
?
*/?
Abstract.Insertion?
=?function(adjacency)?{?
??
this.adjacency?=?adjacency;?
}?

Abstract.Insertion.prototype?
=?{?
??initialize:?
function(element,?content)?{?
????
this.element?=?$(element);?
????
this.content?=?content;?
????
????
if?(this.adjacency?&&?this.element.insertAdjacentHTML)?{?
??????
this.element.insertAdjacentHTML(this.adjacency,?this.content);?
????}?
else?{?
?????
/**?
??????*?gecko?不支持?insertAdjacentHTML?方法,但可以用如下代碼代替?
??????
*/?
??????
this.range?=?this.element.ownerDocument.createRange();?
?????
/**?
??????*?如果定義了?initializeRange?方法,則實行,這里相當與定義了一個抽象的?initializeRange?方法?
??????
*/?
??????
if?(this.initializeRange)?this.initializeRange();?
??????
this.fragment?=?this.range.createContextualFragment(this.content);?

?????
/**?
??????*?insertContent?也是一個抽象方法,子類必須實現?
??????
*/?
??????
this.insertContent();?
????}?
??}?
}?

/**?
?*?prototype?加深了我的體會,就是寫js?如何去遵循 Don’t?Repeat?Yourself?(DRY)?原則?
?*?上文中?Abstract.Insertion?算是一個抽象類,定義了名為 initializeRange?的一個抽象方法?
?*?var?Insertion?=?new?Object() 建立一個命名空間?
?*?Insertion.Before|Top|Bottom|After?就象是四個java中的四個靜態內部類,而它們分別繼承于Abstract.Insertion,并實現了initializeRange方法。?
?
*/?
var?Insertion?=?new?Object();?

Insertion.Before?
=?Class.create();?
Insertion.Before.prototype?
=?(new?Abstract.Insertion('beforeBegin')).extend({?
??initializeRange:?
function()?{?
????
this.range.setStartBefore(this.element);?
??},?
??
??
/**?
???*?將內容插入到指定節點的前面,?與指定節點同級?
???
*/?
??insertContent:?
function()?{?
????
this.element.parentNode.insertBefore(this.fragment,?this.element);?
??}?
});?

Insertion.Top?
=?Class.create();?
Insertion.Top.prototype?
=?(new?Abstract.Insertion('afterBegin')).extend({?
??initializeRange:?
function()?{?
????
this.range.selectNodeContents(this.element);?
????
this.range.collapse(true);?
??},?
??
??
/**?
???*?將內容插入到指定節點的第一個子節點前,于是內容變為該節點的第一個子節點?
???
*/?
??insertContent:?
function()?{??
????
this.element.insertBefore(this.fragment,?this.element.firstChild);?
??}?
});?

Insertion.Bottom?
=?Class.create();?
Insertion.Bottom.prototype?
=?(new?Abstract.Insertion('beforeEnd')).extend({?
??initializeRange:?
function()?{?
????
this.range.selectNodeContents(this.element);?
????
this.range.collapse(this.element);?
??},?
??
??
/**?
???*?將內容插入到指定節點的最后,于是內容變為該節點的最后一個子節點?
???
*/?
??insertContent:?
function()?{?
????
this.element.appendChild(this.fragment);?
??}?
});?


Insertion.After?
=?Class.create();?
Insertion.After.prototype?
=?(new?Abstract.Insertion('afterEnd')).extend({?
??initializeRange:?
function()?{?
????
this.range.setStartAfter(this.element);?
??},?

??
/**?
???*?將內容插入到指定節點的后面,?與指定節點同級?
???
*/?
??insertContent:?
function()?{?
????
this.element.parentNode.insertBefore(this.fragment,?
??????
this.element.nextSibling);?
??}?
});?

prototype 還有兩個源碼文件 effects.js compat.js 就不貼出來了。兩者并不常用,effects.js 看example 做花哨的效果還不錯,不過代碼中沒有太多新鮮的東西。

需要指出的就是
compat.js 中 Funcation.prototype.apply 的實現有兩個錯誤(應該是拼寫錯誤), 我分別貼出來,大家比較一下就清楚了。?

/*?這是包含錯誤的原版本?
if?(!Function.prototype.apply)?{?
//?Based?on?code?from?http://www.youngpup.net/?
Function.prototype.apply?=?function(object,?parameters)?{?
var?parameterStrings?=?new?Array();?
if?(!object)?object?=?window;?
if?(!parameters)?parameters?=?new?Array();?

for?(var?i?=?0;?i?<?parameters.length;?i++)?
parameterStrings[i]?=?'x['?+?i?+?']';?//Error?1?

object.__apply__?=?this;?
var?result?=?eval('obj.__apply__('?+?//Error?2?
parameterStrings[i].join(',?')?+?')');?
object.__apply__?=?null;?

return?result;?
}?
}?
*/?

if?(!Function.prototype.apply)?{?
??Function.prototype.apply?
=?function(object,?parameters)?{?
????
var?parameterStrings?=?new?Array();?
????
if?(!object)?object?=?window;?
????
if?(!parameters)?parameters?=?new?Array();?

????
for?(var?i?=?0;?i?<?parameters.length;?i++)?
??????parameterStrings[i]?
=?'parameters['?+?i?+?']';?

????object.__apply__?
=?this;?
????
var?result?=?eval('object.__apply__('?+?parameterStrings.join(',?')?+?')');?
????object.__apply__?
=?null;?

????
return?result;?
??}?
}?

?

//接下來是我模仿著編寫的一個?Effect?的一個子類,用來實現閃爍的效果。
Effect.Blink?=?Class.create();?
Effect.Blink.prototype?
=?{?
??initialize:?
function(element,?frequency)?{?
????
this.element?=?$(element);?
????
this.frequency?=?frequency?frequency:1000;?
????
this.element.effect_blink?=?this;?
????
this.blink();?
??},?

??blink:?
function()?{?
????
if?(this.timer)?clearTimeout(this.timer);?
????
try?{?
??????
this.element.style.visibility?=?this.element.style.visibility?==?'hidden'?'visible':'hidden';?
????}?
catch?(e)?{}?
????
this.timer?=?setTimeout(this.blink.bind(this),?this.frequency);?
???}?
};?


?使用也很簡單, 調用 new Effect.Blink(elementId) 就好了。

通過對 prototype 源碼的研究,我想我對javascript又有了一點新的體會,而最大的體會就是 《Ajax : A New Approach to Web Applications》文章最后作者對設計人員的建議: to forget what we think we know about the limitations of the Web, and begin to imagine a wider, richer range of possibilities.

轉載于:https://www.cnblogs.com/savageworld/archive/2007/05/05/735994.html

總結

以上是生活随笔為你收集整理的【转】一个优秀的Javascript框架--Prototype解说的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。