在写面向对象的WEB应用程序方面JavaSciprt是一种很好的选择.它能支持OOP.因为它通过原型支持继承的方式和通过属性和方法的方式一样好.很多开发者试图抛弃JS,试着用C#或JAVA仅是因为JS不是他认为合适的面向对象的语言.许多人还没有认识到javascript支持继承.当你写面向对象的代码时.它能给你很强大的能量.你也可以使用它写出可复用,可封装的代码.
对象为何如此伟大?
面向对象思想的成功是由于它仿照了现实中的事物和事物的联系.事物有属性和方法.如果我们描述一个台灯.我们会说它的高度和宽度,比如12CM."开灯"这个动作是它的方法.当它是处于开着的状态时.它可以被调亮一点或暗一点(也就是亮度这个属性值变大或变小).
javascript 给予了为WEB应用程序创建对象的能力.对象在需要的时候相应的事件会被触发,代码封装后,它能被实例化很多次.
用 new Object() 来创建对象
在javascript里有几种创建对象的方法,在不同的场合可用不同的方法.最简单的就是用 new 操作符,例如:
1<script language="javascript" type="text/javascript">
2<!--
3
4person = new Object()
5person.name = "Tim Scarfe"
6person.height = "6Ft"
7
8person.run = function() {
9this.state = "running"
10this.speed = "4ms^-1"
11}
12
13//-->
14</script>
15
16
我们在这个例子里定义了person这个对象,然后加入了它的属性和方法.在这个例子里,自定义的方法里有两个属性.
用文字记号Literal Notation创建对象
用文字记号也可以创建对象,它的创建形式是多样的.
1<script language="javascript" type="text/javascript">
2<!--
3
4// Object Literals
5
6timObject = {
7property1 : "Hello",
8property2 : "MmmMMm",
9property3 : ["mmm", 2, 3, 6, "kkk"],
10method1 : function(){alert("Method had been called" + this.property1)}
11};
12
13timObject.method1();
14alert(timObject.property3[2]) // will yield 3
15
16var circle = { x : 0, y : 0, radius: 2 } // another example
17
18// nesting is no problem.
19var rectangle = {
20upperLeft : { x : 2, y : 2 },
21lowerRight : { x : 4, y : 4}
22}
23
24alert(rectangle.upperLeft.x) // will yield 2
25
26//-->
27</script>
28
29
文字记号可是是数组,也可以是任意的javascript表达式或值.
用 new 操作符或文字记号创建一个自定义对象都是简单的,也是符合逻辑的.但它最大的缺点就是结果不可复用.也不能很容易的用不同的版本初始化创建对象.例如上面的第一个例子,如果 person 的 name 不是 "Tim Scarfe",那样我们不得不重新定义整个对象,仅仅为了适应它的一点点改变.
对象的构造和原型
在OOP的世界里,用先前的方法定义对象在许多场合都有限制.我们需要一种创建对象的方法,类型可以被多次使用而不用重新定义.对象在实例化时每次都可以按需分配不同的值.实现这个目标的标准方法是用对象构造器函数.
一个对象构造器只不过是个有规则的javascript函数,它就象一个容器(定义参数,调用其他函数等等).它们两者所不同的是构造器函数是由 new 操作符调用的.(你将在下面的例子中看到).基于函数语法形式的对象定义,我们可以使它工作得最好.
让我们用现实世界中的猫来举个例子.猫的 name 和 color 是猫的属性.meeyow(猫叫)是它的一个方法.重要的是任何不同的猫都可能有不同的 name 和 meeyow 的叫声.为了建立适应这些特征的对象类,我们将使用对象构造器.
1<script language="javascript" type="text/javascript">
2<!--
3
4function cat(name) {
5this.name = name;
6this.talk = function() {
7alert( this.name + " say meeow!" )
8}
9}
10
11cat1 = new cat("felix")
12cat1.talk() //alerts "felix says meeow!"
13
14cat2 = new cat("ginger")
15cat2.talk() //alerts "ginger says meeow!"
16
17//-->
18</script>
19
20
在这里,函数 cat() 是一个对象构造器,它的属性和方法在函数体里用this来定义,用对象构造器定义的对象用 new 来实例化.注意我们如何非常容易的定义多个cat 的实例.每一个都有自己的名字,这就是对象构造器带给我们的灵活性.
构造器建立了对象的蓝图.并不是对象本身.
在原型里增加方法.
在上面我们看到的例子里,对象的方法是在构造器里定义好的了.另外一种实现的途径是通过原型(prototype).xxx
原型是javascript继承的一种形式.我们可以为对象定义好后,再创造一个方法.原来所有对象的实例都将共享.
让我们来扩展最初的 cat 对象.增加一个改名的方法.用 prototype 的方式.
1<script language="javascript" type="text/javascript">
2<!--
3
4cat.prototype.changeName = function(name) {
5this.name = name;
6}
7
8firstCat = new cat("pursur")
9firstCat.changeName("Bill")
10firstCat.talk() //alerts "Bill says meeow!"
11
12//-->
13</script>
14
15
就象你所看到的.我们仅只用了 关键字 prototype 实现了在对象定义后马上增加了changeName方法.这个方法被所有的实例共享.
用原型(prototype) 重载 javascript 对象
原型 在自定义对象和有选择性的重载对象上都可以工作.比如 Date() 或 String
子类和超类
在JAVA 和C++里,有关于类层次的外在概念.每一个类能有一个角色.
In Java and C++, there is an explicit concept of the class hierarchy. i.e. Every class can have a super class from which it inherits properties and methods. Any class can be extended, or sub-classed so the resulting subclass can inherit its parent's behavior. As we have seen, javascript supports prototype inheritance instead of class based. It's possible for inheritance to happen other ways, however.
The following is an example of inheritance through functions.
下面一个例子演示了如何继承通过function .
1<script language="javascript" type="text/javascript">
2<!--
3
4// thanks to webreference
5
6function superClass() {
7this.supertest = superTest; //attach method superTest
8}
9
10function subClass() {
11this.inheritFrom = superClass;
12this.inheritFrom();
13this.subtest = subTest; //attach method subTest
14}
15
16function superTest() {
17return "superTest";
18}
19
20function subTest() {
21return "subTest";
22}
23
24
25var newClass = new subClass();
26
27alert(newClass.subtest()); // yields "subTest"
28alert(newClass.supertest()); // yields "superTest"
29
30//-->
31</script>
32
33
基于继承的原型是遥远的.为 javascript 应用程序在许多场合.
(基于原型的继承在许多javascript的应用场合是非常有用的.)
对象作为联合数组
正如你所知, (.)操作符能够用来存储.[] 操作符用来操作数组.
1<script language="javascript" type="text/javascript">
2<!--
3
4// These are the same
5object.property
6object["property"]
7
8//-->
9</script>
10
11<SCRIPT LANGUAGE="javascript">
12<!--
13function Circle (xPoint, yPoint, radius) {
14this.x = xPoint;
15this.y = yPoint;
16this.r = radius;
17}
18
19var aCircle = new Circle(5, 11, 99);
20alert(aCircle.x);
21alert(aCircle["x"]);
22//-->
23</SCRIPT>
How do I loop through properties in an object?You need to use a for/in loop.
我们可以通过for in循环来遍历对象的属性。
1<script language="javascript" type="text/javascript">
2<!--
3
4var testObj = {
5
6prop1 : "hello",
7prop2 : "hello2",
8prop3 : new Array("hello",1,2)
9}
10
11for(x in testObj) alert( x + "-" + testObj[ x ] )
12
13//-->
14</script>
15
16<SCRIPT LANGUAGE="javascript">
17<!--
18var Circle = { x : 0, y : 1, radius: 2 } // another example
19
20for(p in Circle)
21alert( p + "-" + Circle[ p ] )
22
23//-->
24</SCRIPT>
The important thing to notice is that in the object syntax the property is an identifier, whereas in the array syntax, it's a string. The obvious benefits of using an array syntax to access an object is because of the literal data type, you can easily concat strings and play around with them to access an object. For this to work with the standard syntax, an eval() would need to be used.
应该值得注意的是对象的属性只是一个标识字符,尽管在一个数组里是一个字符串,因为是一个literal的数据类型,所以有利于使用数组的方式的操作一个对象。你也可以很容易的存取一个对象在标准的语句中。这个时候eval()函数可能用得到。
1<script language="javascript" type="text/javascript">
2<!--
3
4testObj = {
5
6prop1 : "hello",
7prop2 : "hello2",
8prop3 : new Array("helloa",1,2)
9}
10
11for(x in testObj) alert( x + "-" + testObj[ x ] )
12var prop3 = testObj["prop3"];
13alert(prop3);
14//alert(prop[1]);
15alert(typeof(prop3));
16alert(eval(prop3)[1]);
17alert(typeof(eval(prop3)[1]));
18
19//-->
20</script>
待续......