(一).序言
在寫這個指南之前,先介紹一下Prototype主要是干嗎的,如果你比較關注ajax/javascipt方面的應用,你應該早就聽說過這個 javascript framework。 Prototype是一個基礎的javascript應用框架,先引用一段官方網站的介紹
Prototype is a JavaScript framework that aims to ease development of dynamic web applications. Featuring a unique, easy-to-use toolkit for class-driven development and the nicest Ajax library around, Prototype is quickly becoming the codebase of choice for web application developers everywhere.
根據作者自己的介紹,Prototype的目的是為了更方便的開發javascript的應用,使用它可以更加方便簡單的使用javascript編程,開發出面向對象的javascript程序,Prototype中包含包含了一個功能強大好用的ajax框架,Prototype是一個基礎性的框架,很多更高層次的框架都以它為基礎,例如scriptaculous效果庫
Prototype中包含一下幾個部分:
base: Prototype中應用的基本功能,基本上其他所有部分都依賴于它,包括用于面向對象風格的Class.create和Object.extend,一個Try對象,函數綁定,number擴展,PeriodicalExecuter(周期性執行某個函數的功能)等
string: 對String原型的擴展,為string添加了strip,escapeHTML等等好用的方法
enumerable: 枚舉類型(array, hash, range等)的父類對象,提供枚舉類型的共同方法
array: 對Array原型的擴展,為array添加了indexOf、without等方法
hash: 為javascript提供了一個好用簡單的Hash實現
range: 繼承于enumerable,一個范圍(例如3—67)對象
ajax: 一個功能強大好用的ajax框架
dom: 對基于瀏覽器的開發提供了很好的跨瀏覽器封裝,并添加很多強大的功能
selector: 提供了使用class,css等選擇元素的功能
form: 關于表單的一些功能
event: 簡單的夸平臺事件封裝
position: 提供了一些關于元素位置方面的功能
可以說Prototype就想一把瑞士軍刀,為javascipt封裝了很多通用的功能,大大簡化了javascript應用的開發,給javascript開發人員增添了很大的信心,Prototype可以運行于以下平臺,使用它再也不用各種跨平臺等問題煩惱了
* Microsoft Internet Explorer for Windows, version 6.0 and higher
* Mozilla Firefox 1.0/Mozilla 1.7 and higher
* Apple Safari 1.2 and higher
不過要注意的是:要想很好的理解Prototype,應該首先理解一下javascript面向對象開發的一些知識以后的文章將對Prototype中具體的每個功能中的方法做一個詳細的介紹,包括作用,實例等Prototype官方網站是:http://prototype.conio.net/ ,目前發布版還只是1.4, 但是現在的1.5已經發生了很大的變化,而且很多基于prototype的庫使用的都是1.5的,所以強烈建議通過svn下載最新版代碼
(二).Prototype(1.5 rc2)使用指南之base.js
base.js中包含下面的內容
類的創建與繼承:
Class.create(): 創建一個類,例如 person=Class.create()
Object.extend(destination, source): 把source中方法屬性copy到destination(使用for property in source),需要注意的是,javascript中除了基本類型(Number, Boolean)外都是引用類型,所以這種copy一般只是copy引用而已,destination和source還是指向同一個方法或對象屬性 (function array object)
在面向對象的編程中,一般通過Class.create新建一個類,如果這個類繼承于另一個類,一般使用Object.extend (class.prototype, parentClass.prototype)或者Object.extend(class.prototype, aparentClassInstance)
Object構造函數的擴展:
Object是其他對象實例的構造函數(var a=new Object()),也是所有其他類的父類,對Object直接擴展(注意不是擴展Object.prototype,擴展 Object.prototype相當于添加實例方法)相當于為Object類添加靜態方法
Object.inspect(object): 調用object的inspect(如果定義了)或toString方法,返回一個對象的字符串表示
Object.keys(object): 返回一個對象的所有屬性和方法名稱組成的數組, 例如Object.keys(document.body)
Object.values(object):返回一個對象的所有屬性和方法的值組成的數組, 例如Object.values(docuement)
Object.clone(object): 返回一個對象的clone版本,其實是執行Object.extent方法把object中的方法屬性copy到一個新對象中,然后返回這個對象
函數邦定:
定義了Function對象的兩個方法,bind和bindAsEventListener,這兩個方法是一個函數的兩個方法,對于java、c#程序員來說,看到這個也許感到很驚訝,因為在他們看來函數只是一個程序語句組織結構而已—>怎么還有方法,而且還可以擴展?這也是javascript等腳本語言相對于java等一個非常強大的功能,函數也是一個對象,函數名就是這個對象的名稱,只要你愿意,你也可以使用 new Function(…)來定義函數,所以為函數定義方法也就很正常不過了
這兩個函數的主要作用是為了解決使用javascript面向對象風格編程中this的引用問題,在javasctipt中this關鍵字始終指向調用該函數的對象或者指向使用call,apply方法指定的對象(具體這方面的知識可以自己google一下,以下系列對prototype的介紹也假設讀者對javascript語言比較熟悉了,如果不熟悉可以找本javascript權威指南這本書看看)要理解這個問題首先要理解始終指向這個問題,就是this這個關鍵字比較特殊,不能把他當成一般的變量名看待,最常見的一個錯誤就是在返回函數的調用中使用this,例如return function(){this.aMethod()}, 當你下次調用這個返回的匿名方法時,這個this引用的內容又指向了調用這個函數的對象了,記住的一點的this是個關鍵字,不是變量名,不會產生閉包
對Number的擴展(注意num也可以看成對象,其實是在使用的時候系統自動打包成Number對象):
toColorPart:把數字轉換為可以用于表示color的16進制值:例如 7.toColorPart()=>"07",28.toColorPart()=>"1C"
succ: 返回num++, 但不改變num本身的值,其實就是 return this+1
times:對從0到這個數字輪流調用一個函數, 例如function a(n){docuement.write(n)}, 10.times(a), 將顯示012345678910, 注意函數也是一個對象,而且與其他對象并沒有實質的區別
Try對象: Try對象提供了一個很有趣的功能, 先看一下如下的代碼:
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject(’Msxml2.XMLHTTP’)},
function() {return new ActiveXObject(’Microsoft.XMLHTTP’)} )
|| false;
}
}
Try對象提供了一個方法these, 這個方法接受一個函數類型的參數列表,然后輪流執行這些函數,當其中一個函數沒有產生錯誤時,就停止執行,并且返回這個函數返回的值,自己慢慢體會吧
PeriodicalExecuter(周期性執行器)對象
這個對象是對setInterval方法的簡單封裝,使用方法如下
var a=new PeriodicalExecuter(callback, frequency ) ,其中callback指要執行的函數名 frequency指每次執行的時間間隔
要停止的話,調用這個對象的stop方法就可以了 a.stop()
(三)Prototype(1.5 rc2)使用指南之string.js
下面介紹Prototype對String對象的擴展部分:
這部分主要為string對象添加了幾個很有用的方法:
strip(): 去掉字符串兩邊的空白, 例如" jj ".strip()返回"jj"
stripTags():去掉字符串中的html標簽
stripScripts(): 去掉字符串中的javascript代碼段
extractScripts(): 返回字符串中的javascript代碼,返回數組
evalScripts(): 執行字符串中的javascript代碼
escapeHTML():將字符串中的html代碼轉換為可以直接顯示的格式, 例如將< 轉化為 < ,在ie6中有bug,執行這個操作返回的字符串,將多個連在一起的空白變成了一個,所以很多換行什么的都被去掉了
unescapeHTML(): escapeHTML的反向過程
truncate(length, truncation): 截斷,例如"abcdefghigkl".truncate(10)返回abcdefg…, truncation默認為"…" toQueryParams(separator)/parseQuery(separator):將一個querystring轉化為一個hash表(其實是一個對象,在javascript中對象可以當成hash表來用,因為對象的屬性或方法可以通過object[propertyName]來訪問)
toArray(): return this.split('’), 轉化為一個字符數組
camelize(): 將background-color的形式轉化為backgroundColor形式,用在style/css中
capitalize(): 返回一個首字母大寫的字符串
inspect(useDoubleQuotes): 返回字符串的表示形式, 例如"sdfj""sfa".inspect() 返回“’sdfj"sfa’”
gsub(pattern, replacement):pattern是一個正則表達式,replacement是一個函數(或者是一個template字符串),對于字符串中每個匹配pattern的部分使用replacement處理,然后將 replacement返回的值將原來匹配的部分替換掉,例如"skdjfAsfdjkAdk".gsub(/A/,function(match) {return match[0].toLowerCase()}), 將字符串所有的A轉化為a, 注意pattern中不要添加g選項,因為gsub會遞歸的執行match方法
sub(pattern, replacement, count) :gsub的另一種形式,不過可以設置執行的次數
scan(pattern, iterator): 跟gsub差不多,但是返回的是字符串本身,也就是說對于pattern中的每個匹配執行iterator,但是不返回替換的字符串"skdjfAsfdjkAdk".gsub(/A/,function(){alert have a A’})
underscore(): 'borderBottomWidth’.underscore() -> 'border_bottom_width’
dasherize(): 'Hello_World’.dasherize() -> 'Hello-World’
Template模板類:
使用方法:
var template = new Template(replacement, pattern);
template.evaluate(object) 有點像php中的模板,默認(沒有提供pattern)將{propertyName}形式的東西替換了object的屬性值
(四).Prototype(1.5 rc2)使用指南之Enumerable.js
Enumerable是一個抽象對象(需要說明的是,javascript中并沒有類的概念,所指的類也就是一個函數,繼承一般指的是一個對象(父)將它的方法屬性copy(通過Object.extend, copy的是引用)到子類(函數)的prototype屬性(一個對象)中)
Enumerable不能直接使用,它被很多枚舉類型(Hash、Array、Range等)所繼承,繼承的類型都要實現一個_each方法,提供具體類型的枚舉方法
Enumerable為其他子類提供了如下的方法:
each(iterator): iterator是一個函數對象, 這個方法調用具體類型的_each方法對自身包含的每個對象調用iterator,例如如果Enumerable具體指的是一個Array,eg: var a=[2,3,4], 則a.each(iterator)方法將依次調用iterator(2,0) ,iterator(3,1), iterator(4,3),其中第二個參數指的是索引。這個方法幾乎在Enumerable中的每個方法中都要用到
eachSlice(number, iterator):將Enumerable 類型對象每個每個按照number分開,例如[1,2,3,4,5].eachSlice(3)=>[[1,2,3],[4,5]], 沒有提供iterator, 則iterator=Prototype.K: function(k){return k},Prototype中的很多iterator默認值都是這個,或者是Prototype.emptyFunction: function() {},其實實際上返回的是[iterator([1,2,3]),iterator([4,5])]
all(iterator): 對Enumerable類型中的每個值調用iterator,如果其中有一個返回false,則返回false,否則返回true,相當于判斷是否每個值執行iterator都是"true"
any(iterator): 跟all相反,判斷是否每個值都是"false"(是否有一個值是true)
collect(iterator)/map: 對每個值調用iterator,將結果組成一個新的數組返回
detect(iterator)/find: 對每個值調用iterator,如果有一個不為false,則返回這個執行iterator后不為false的值(不是返回執行iterator后的值),相當于找出第一個真值
findAll(iterator)/select: 相當于detect, 但是找出所有的真值,返回一個數組
grep(pattern, iterator):返回所以符合pattern的值,iterator提供的話,則返回執行iterator的值
include(object)/member: 數組中是否包含object
inGroupsOf(number, fillWith): eachSlice的變異版本,按照number將對象分開,如果分開后的數組的最后一個值的length小于number, 則用fillwith填充, 例如[1,2,3,4,5].inGroupsOf(3)=>[[1,2,3],[4,5,null]]
inject(memo, iterator): 注入
invoke(method): 調用
max(iterator): 最大值
min(iterator): 最小值
partition(iterator): 分離
pluck(property): 采集
reject(iterator): 不合格的產品, 于findAll相反
sortBy(iterator): 根據iterator排序,如果調用的對象是Array的話,直接調用內置的sort(iterator)就行了
toArray()/entries: 將調用對象的每個值組成一個數組返回
zip(): 例如[2,3,4].zip([5,6,7])=>[[2,5],[3,6],[4,7]], 如果最后一個參數類型為function,將返回[iterator([2,5]),iterator([3,6]),iterator([4,7])],
inspect(): Enumerable對象的字符串表示
------君臨天下,舍我其誰
------