ajax in action——javascript面向对象编程(上)

来源:互联网 发布:travel域名 编辑:程序博客网 时间:2024/05/20 20:56

   有许许多多的办法成为一个javascript程序员,业界曾经有过图形设计人员变成严谨的程序人员的事。这里可不是要告诉你怎么变成一个javascript程序人员的,因为有太多的书籍你可以看,不需要在这里再啰嗦了。我的意图是让java和c#程序人员顺利的理解javascript。如果你是一个习惯于严格oo编程的人,那么你第一次接触javascript就会受到c#和java的严重影响,并且你会发现你对他有相当的抵触情绪。我是这样按照自己的经验思路去思考他。
javascirpt可以作出许多比java和c#更多的技巧,它可以帮助你写出更好的代码。了解这些技巧的价值是避免使用时的误区。如果你是一个c++或者java的使用者,目的是学习ajax,我想对你是有帮助的,至少对我的帮助不是一两天了。
B.1  javascript不是java
为什么javascript中会存在java这个词汇呢?这是出于推广的需要。网景的行销部门把它的命名,从livescirpt改为javascirpt,现在已经把他们“粘牢“了的。通常的主流的看法是:javascript不是派生于c家族,因为它缺乏太多的语言功能例如Scheme和Self,而且它有许多Python的特征。除了名字,语法构造上他也很类似java,但是虽然由那么一些地方很类似java,但是大部分地方和java有很大区别。
表B1总结了这些关键差别:
特征
描述
变量是宽松类型的
变量命名之后,并不是属于某一种类型,在javascript中可以任意赋值
代码是动态解析的
在运行时,代码存储在文本中并且被机器指令解释执行,与之相对的预编译语言如java和c#。你的站点用户一般可以看到你的ajax源代码。此外,他也可以被其他代码动态的产生,
javaScript的function是一等对象
一个java类的方法的调用必须通过一个对象来实现。javasript的function可一个附着到对象上,因此他们看起来像一个方法,但是他们也可以调用其它的上下文以及在运行时刻附着到其他对象。
javascript对象是基于原型的
一个java,c++或者c#对象肯定属于某个超类或者接口。严格的定义了它的功能。所有的的javascript对象都是一个对象,由一个联合数组来伪饰。原型使得javascript可以模仿java的风格,当然只是表层的。

这些差异使得语言可以多方面的应用,同时也展示了许多怪异的又非常有用的窍门,可能来自于一个熟悉Lisp的黑客。如果你是一个够聪明的开发人员,你可能会用这些窍门做一些非凡的事情,甚至可能写了超过几百行的代码。另一方面,如果你真的认为你非常聪明和自立,那么你就应该能够随机应变 。
我试过好多次发现保持问题的简单化是一个好事。如果你在团队中工作,你的编码将按照技术主管的感觉来制定。
不管怎样,理解这些差异和技巧有另外一个原因:它是在浏览器中运行的,理解它可以节约你痛苦的调试他的时间。细节上,我发现明白javascript和java之间只是形似这个道理对你是很有帮助的。
读到这里,你认识到JavaScript的真实面貌展示出来了,他们怎么组织成员函数和变量的,什么是javascirpt能够实现的功能。
B2  javaScript中的对象
      对象对于javascirpt可不是非的需要不可,可以写一个程序放在文本中然后又解释器执行解释。可是如果代码的体积很大,那么组织这些代码就显得非常的必要,我们推荐你用对象。
简单的如下:
var myObject=new Object();
我们在2.2能够看到他实际的使用,我们的这个对象初始状态为空,没有成员和方法。附加他们是很简单的。
B.2.1建一个专门对象
       我们注意到,javascript对象本质上是一个联合数组,对象名作为他的成员和方法的主健。类似于c的语法为的是让c系列的程序员看起来的亲切一些,但是暗地里它走了另一个路。我们可以按照我们想象的那样去一行一行的构建复杂的对象,添加方法和成员。
       在这个ad hoc中我们有两个途径来构建对象,第一是简单的建立一个javaScript对象,第二是用著名的的JSON。现在我们就开始。
Using JavaScript statements
        在繁杂的代码中,我们可以为对象属性赋值。JavaScript对象的属性是可读写的并且能够用=赋值。我们为我们的简单对象赋予属性:
myObject.shoeSize="12";
        在oo语言中,我们需要定义个类并且声明一个属性shoeSize或者遭遇编译错误。javaScript不是这样,事实上如同我们说得他是一个类似数组结构,我们能够这样引用他:
myObject['shoeSize']="12";
        这个笨拙而的用法为我们说明了他的数组索引是一个表达式。请看B.2.4.
        我们也能够动态的为对象加入函数:
myObject.speakYourShoeSize=function(){
alert("shoe size : "+this.shoeSize);
}
或者预先确定:
function sayHello(){
alert('hello, my shoeSize is '+this.shoeSize);
}
...
myObject.sayHello=sayHello;
        注意,我们预先定义的函数赋给对象的时候没有括号。如果你这样写:
myObject.sayHello=sayHello();
意味着将一个函数的返回支付给对象属性。这里是null;
我们还可以将一个对象附着到另一个对象上面形成更复杂的结构:
var myLibrary=new Object();
myLibrary.books=new Array();
myLibrary.books[0]=new Object();
myLibrary.books[0].title="Turnip Cultivation through the Ages";
myLibrary.books[0].authors=new Array();
var jim=new Object();
jim.name="Jim Brown";
jim.age=9;
myLibrary.books[0].authors[0]=jim;

这种用法容易让人讨厌,JavaScript提供了一种简洁的符号来代表,那就是JSON。让我问来看看。

使用 JSON
JavaScript对象标示(JSON)是语言的核心特征之一。它规定了一个规则用来构建数组和In order。要理解JSON,我们需要知道javaScript数组是怎么工作的,因此我们首先数组怎么用:
JavaScript已经有个一个Array类,能够用新的关键子命名:
myLibrary.books=new Array();
数组可以给每一项赋值,就像C或者java一样:
myLibrary.books[4]=somePredefinedBook;
或者他也可以如同java的Map或者Python的Dictionary,用关键字来关联:
myLibrary.books["BestSeller"]=somePredefinedBook;
这是一个很好的调整,但是如果一开始就要定义一个数组作者对现实不舒服的。在方括号中用数字索引,可以用一组用逗号隔开的列表,例如:
myLibrary.books=[predefinedBook1,predefinedBook2,predefinedBook3];
也可以用冒号隔开的名字对:
myLibrary.books={
bestSeller              : predefinedBook1,
cookbook              : predefinedBook2,
spaceFiller           : predefinedBook3
};
在所有的表示符号中,空白被忽略,他的目的是让我们清晰的排版出来。关键子能够存在空白间隔,能够在JSON符号中被引用,例如:
"Best Seller" : predefinedBook1,
或者我们可以个这样构建:
var myLibrary={
location : "my house",
keywords : [ "root vegetables", "turnip", "tedium" ],
books: [
{
title : "Turnip Cultivation through the Ages",
authors : [
{ name: "Jim Brown", age: 9 },
{ name: "Dick Turnip", age: 312 }
],
publicationDate : "long ago"
},
{
title : "Turnip Cultivation through the Ages, vol. 2",
authors : [
{ name: "Jim Brown", age: 35 }
],
publicationDate : new Date(1605,11,05)
}
]
};
在这里我们为myLibrary对象赋了三个属性:location是单一一个字符串,keyWords是一个由数字索引的字符串列表,books是一个数字索引的对象列表,分别是书名,作者和出版时间,书名是一个字符串,作者是一个数组对象,出版时间是一个时间对象。每一个作者又是包括名字和年龄。JSON为我们规定了简单的构建这些的信息的机制。
细心的读者可能已经注意到第二本书的出版日期上我们已经用了一个日期对象。事实上我们可以为它赋予任何对象,甚至一个我们自己定义的函数:
function gunpowderPlot(){
return new Date(1605,11,05);
}
var volNum=2;
var turnipVol2={
title : "Turnip Cultivation through the Ages, vol. "
+volNum,
authors : [
{ name: "Jim Brown", age: 35 }
],
publicationDate : gunpowderPlot()
}
]
};
这里书名是一个动态计算的表达式结果,作者是预先定义个函数的返回值。在这个例子中我们预先定义个函数gunpowderPlot(),事实上我们可以为对象定一个成员函数,可以被对象在以后调用。
var turnipVol2={
title : "Turnip Cultivation through the Ages, vol. "+volNum,
authors : [
{ name: "Jim Brown", age: 35 }
],
publicationDate : gunpowderPlot()
}
],
summarize:function(len){
if (!len){ len=7; }
var summary=this.title+" by "
+this.authors[0].name
+" and his cronies is very boring. Z";
for (var i=0;i<len;i++){
summary+="z";
}
alert(summary);
}
};
...
turnipVol2.summarize(6);
summarize()函数具有所有的javascirpt语言的特征,例如一个参数和一个可以被this关键字引用的上下文对象id,一旦对象建立,他不过是另一个javascript对象,我们可以把他和javaScript和json符号混合在一起,只要我们喜欢。我们能够用javascirpt调整在JSON中定义的对象:
var numbers={ one:1, two:2, three:3 };
numbers.five=5;
我们用json的方法定义了一个对象然后用js的方法附加了个一个元素。同样我们也可以在js对象中使用json:
var cookbook=new Object();
cookbook.pageCount=321;
cookbook.author={
firstName: "Harry",
secondName: "Christmas",
birthdate: new Date(1900,2,29),
interests: ["cheese","whistling",
"history of lighthouse keeping"]
};
我们可以通过js内置对象,Array类或者json,建立一个我们想要得复杂级别的对象,也可以都不用。javaScript也为面向对象的程序有一个的途径,可以用来建立对象,让我们接着看。
B.2.2构造函数,类,和原型
在面向对象编程中,我们通常实例一个类得到一个对象。不管java还是javascript都有一个new的关键词,他们都允许我们实例一个对象。这一点他们是相同的。
在java中,任何事都是对象,他们继承自同一个基类java.lang.Object。java虚拟机默认理解类,成员,和方法。在我们定义个对象:
MyObject myObj=new MyObject(arg1,arg2);
我们首先声明了对象的类型,然后用它的构造函数实例化。MyObject对象构造的关键是他已经被声明并且首先提供了构造函数。
javaScript也一样有对象和类的概念,但是他没有内置继承。事实上,每一个javaScript对象都是一个基类的实例。一次他可能任意的唯一个对象指派属性。MyJavaScriptObject.completelyNewProperty="something";
这个高度自由组合任何东西的机制非常类似于可怜的oo程序员的原型模式,定义的属性和函数在调用的时候被自动的绑定到对象上面。也许构建bject-based并没有考虑到要用到原型模式,但事实上他却在一定程度上体现原型并且很符合oo开发者在开发rich-client应用时的要求。
在javaScript中,我们可以写出很多像java一样的声明var myObj=new MyObject();
但是我们不能定义类MyObject,而使用一个同名字的函数,在这里他是一个构造函数:
function MyObject(name,size){
this.name=name;
this.size=size;
}
我们可以在随后调用:
var myObj=new MyObject("tiddles","7.5 meters");
alert("size of "+myObj.name+" is "+myObj.size);
在构造函数中所有跟在this后面的属性都是对象的一个成员。我们可能想最好能在内部代用alert(),而tiddles能够起到这个作用。通常认为定义一个函数在构造函数:
function MyObject(name,size){
this.name=name;
this.size=size;
this.tellSize=function(){
alert("size of "+this.name+" is "+this.size);
}
}
var myObj=new Object("tiddles","7.5 meters");
myObj.tellSize();
第一步,我们定义了一个构造函数,然后我们为原型附加了一个函数。当我们构建实例的时候,这些功能已经附加上去了。对象实例化之后,用this解决起来起来和原来一样的好。
这里需要注意的是。我们制定一个原型是在构造函数定义之后,对象继承自原型并且只能附加在构造器中声明的功能。当然它的prototype也可以在声明之后添加,这时候的对象和以前的那个已经不一样了:
MyObject.prototype.color="red";
var obj1=new MyObject();
MyObject.prototype.color="blue";
MyObject.prototype.soundEffect="boOOOoing!!";
var obj2=new MyObject();
obj1是红色的,没有声音效果,obj2是蓝色的并且有声音效果!通常我们是不这样做的,他的功能也就是让我们知道有这么一回事发生。但是以一样是确定的,就是可以实现类似于类的行为,并且他是安全可靠的。有趣的是,某些内置类的prototype能够被扩展。现在我们看看怎么工作的。

原创粉丝点击