(一).序言
在写这个指南之前,先介绍一下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对象的字符串表示
------君临天下,舍我其谁
------