基于对象的JavaScript编程(2)
-JavaScript Object-Oriented Programming
By-Ryan Frishberg
在第一部分中,我们已经讨论了对象,对象方法以及对象的类别,现在我们继续。
参数
任何的方法中,一个私有的变量:argument(js自动创建),以数组的形式保存了传道该方法的所有参数。例如:
testArg("PageResource","SitePoint","JavaScriptCity",
"WebSite Abstraction");
来逐个弹出对话框来显示一些我喜爱的web开发站点。
function Person(lastName, firstName){
this.lastName = lastName;
this.firstName = firstName;
}
接着,来创建一些person的对象:
var DnnyGdmn = new Person("Goodman","Danny");
var DvdFlngn = new Person("Flanagan","David");
var TmMyrs = new Person("Myers","Tom");
var AlxNkmvsky = new Person("Nakhimovsky","Alexander");
然后,就要创建我们的book类。他需要包含如下属性:
title
pages
price
author(s)
其中一本书可以有多个作者,所以呢我们就需要接受一到多个person对象做为作者。这样,我们就用一个数组来保存书的作者列表。
function Book(title, pages, price){
this.title = title;
this.pages = pages;
this.price = price;
this.authors = new Array(arguments.length-3);
for(i=0;i<arguments.length-3;i++){
this.authors[i] = arguments[i+3];
}
}
这段代码前半部分很普通,但后面的可能就不是那么直观了。下面详细解析一下这部分:
this.authors = new Array(arguments.length-3);
这行为book类添加了一个author属性:一个数组对象。调用book()这个构造方法的时候前三个参数分别是title,pages和price,这样后面的参数就是作者信息了。显然,如果传入五个参数,剩下的两个参数就必须是作者。这样创建一个长为arguments.length-3. 的数组也就顺理成章了不是?!
arguments.length-3.
for(i=0;i<arguments.length-3;i++){
this.authors[i] = arguments[i+3];
}
这段代码遍历了参数中的作者信息,然后逐个添加到作者数组中,下面具体看看怎么创建一个book对象:
var JavaNut = new Book("Java Foundation Classes in a
Nutshell", 731, 29.95, DvdFlngn);
var JSTDR = new Book("Javascript: The Definitive Guide (3rd
Edition)", 776, 39.95, DvdFlngn);
var JSBible = new Book("Javascript Bible, 4th Edition",
1200, 49.99, DnnyGdmn);
var DHTMLTDR = new Book("Dynamic Html: The Definitive
Reference", 1073, 44.95, DnnyGdmn);
var JSObj = new Book("JavaScript Objects", 450, 39.99,
TmMyrs, AlxNkmvsky);
可以看到我们在建book对象时传入的后面几个参数都是person类型的对象。面向对象的设计方法里有一条原则是避免重复。因此我们就为每个作者建了一个person对象。这样,即使David Flanagan可能写了不止一本书,但是始终指向的都是同一个人。另外如果他想把他的姓改为Behop的话,也只需要把他对应的对象的属性改掉就可以了,而不用找到他写的每一本书逐个改掉。其实上,那些基本数据类型参数我们也可以用对应对象实例替换掉,title属性可以传入一个String型的对象,页数也可以传入Number型对象,但是在这里这样做并没有什么必要,用基本数据类型就完全可以满足需求。
下面继续讨论最难得一个构造函数,Library构造函数。他比较复杂,我们分成几部分来探讨:
function Library(){
this.books = new Array(arguments.length);
for(i=0;i<arguments.length;i++){
this.books[i] = arguments[i];
}
你可能已经注意到这个方法没有显式的参数定义。你说这是为什么呢?-。- 。实际上因为图书馆只接受book类型的对象,但是我们又不知道有多少本书,所以就只能通过别的方式来定义以及取得参数了。可以看到我们定义的books数组属性,他就是用来保存这些book信息的,那个循环应该不用赘述了吧。如果你想去的一本书的第一作者,就可以这样:
this.books[bookIndex].authors[0]
首先取到图书馆的book数组属性。然后得到一个具体的book对象。然后就可以取到这本书的authors属性,在这个数组中包含了该书的所有作者。最后得到的是作者数组中的一个具体person对象。从这个对象里可以得到它的firstName和lastName属性。那个bookIndex是我们想得到的书的索引。
上面的book数组就是我们的library类的所有属性了。剩下的就是方法了:
this.totalPrice = function(){
var totalCost = 0;
for(i=0;i<this.books.length;i++){
totalCost += this.books[i].price;
}
return totalCost;
}
这个方法遍历了books数组中的所有书籍,取到他们的价格信息并进行了累加然后返回。
this.averagePrice = new Function("return this.totalPrice
()/this.books.length");
这个方法一看就明白了,取library中所有书籍的平均价。同时我们可以用下面的方法在已经建好的library对象中添加新的book。
this.addBook = new Function("book", "this.books.push(book)");
这里用了Array的内建方法:push()。这个方法在对应的Array对象上添加新值并同时更新它的length属性。下面我们来建一个显示图书管中所有作者名字的方法。这个方法比较长,分开来讲解:
this.getAuthors = function(){
var toSay = "Your favorite authors are:\n";
这段代码创建一个用来取出作者列表的方法。变量toSay用来做返回值用。
for(i=0;i<this.books.length;i++){
for(j=0; j<this.books[i].authors.length;
j++){
var authName =
this.books[i].authors[j].firstName + " " +
this.books[i].authors[j].lastName;
这段代码也不难,两层循环取到当前作者的firstName和lastName放到了一个新的局部变量authName中。
if(toSay.indexOf(authName)!=-1) continue;
toSay+="\n\t"+authName;
如果在toSay中已经存在当前person的信息,就跳过他继续循环取其他的作者信息,否则就将他的信息累加到toSay中。
最后完成循环,返回结果,方法结束。下面把代码放到一块看看,然后建一个Library实例:
// define our Person() constructor
function Person(lastName, firstName){
this.lastName = lastName;
this.firstName = firstName;
}
// define our Book() constructor
function Book(title, pages, price){
this.title = title;
this.pages = pages;
this.price = price;
this.authors = new Array(arguments.length-3);
for(i=0;i<arguments.length-3;i++){
this.authors[i] = arguments[i+3];
}
}
//define our Library() constructor
function Library(){
this.books = new Array(arguments.length);
for(i=0;i<arguments.length;i++){
this.books[i] = arguments[i];
}
this.totalPrice = function(){
var totalCost = new Number(0);
for(i=0;i<this.books.length;i++){
totalCost += this.books[i].price;
}
return totalCost;
}
this.averagePrice = new Function("return
this.totalPrice()/this.books.length");
this.addBook = new
Function("book","this.books.push(book)");
this.getAuthors = function(){
var toSay = "Your favorite authors are:\n";
for i=0;i<this.books.length;i++){
for(j=0;j<this.books[i].authors.length;j++){
var authName =
this.books[i].authors[j].firstName + " " +
this.books[i].authors[j].lastName;
if(toSay.indexOf(authName)!=-
1)continue;
toSay+="\n\t"+authName;
}
}
return toSay;
}
}
// create some Person objects
DnnyGdmn = new Person("Goodman","Danny");
DvdFlngn = new Person("Flanagan","David");
TmMyrs = new Person("Myers","Tom");
AlxNkmvsky = new Person("Nakhimovsky","Alexander");
// create some Book objects
JavaNut = new Book("Java Foundation Classes in a
Nutshell",731,29.95,DvdFlngn);
JSTDR = new Book("Javascript: The Definitive Guide (3rd
Edition)",776,39.95,DvdFlngn);
JSBible = new Book("Javascript Bible, 4th
Edition",1200,49.99,DnnyGdmn);
DHTMLTDR = new Book("Dynamic Html: The Definitive
Reference",1073,44.95,DnnyGdmn);
JSObj = new Book("JavaScript
Objects",450,39.99,TmMyrs,AlxNkmvsky);
// create a Library object
myLib = new Library(JavaNut,JSTDR,JSBible,DHTMLTDR);
Oops(老外的一种感叹词,。。。),拉掉了一个book对象,最好还是加上吧:(老外就喜欢搞这一套,你要是看过《Head First Design Pattern》这本书的话,相信对这一套也会跟我一样有点胃不是很舒服了。。。)
Ok,大功告成,你可以取得诸如图书馆书籍总价,均价,所有作者名等信息。看到了吧,我们用JavaScript建立了一个完全面向对象的例子。(下面广告时间 跳过 -.-)
Prototype
(这个词也许可以翻译成:原型)
所有的对象构建器(也许说成对象更好)都有这个特殊的属性:prototype。通过它你可以给使用相同构造器创建的对象添加属性/对象。有点晕乎吧,先来看个例子相信你就精神了:
function Square(){
}
var squareObj = new Square();
Square.prototype.side = 5;
var squareObj2 = new Square();
alert(squareObj.side); // displays 5
alert(squareObj2.side); // displays 5
看到了吧,上面代码中我们在Square的实例对象中的prototype属性上添加了一个side属性,初始值为5.然后其他的对象也都有了这个属性。需要注意的是prototype对象(实际上它就是一个对象)在对象的构造函数执行之前首先加载。又有点晕吧 呵呵,继续看代码:
function Square(){
this.side=5;
}
var squareObj = new Square();
Square.prototype.side = 4;
var squareObj2 = new Square();
alert(squareObj.side); // displays 5
alert(squareObj2.side); // displays 5
看到了没,返回值是5而不是4.现在上面那句话应该明白了吧,prototype首先加载。即使Square对象构造器已经运行过,然后你又再prototype上添加或者更新了属性,最终还是会被构造器中的内容覆盖掉(个人理解,只要你更改了prototype,对应对象的构造器就会自动执行一遍)。下面的例子里我们使用了String对象的prototype属性来给String添加新的方法:
function consonantize(){
var consonants ="";
for(i=0;i<this.length;i++){
var l = this.charAt(i);
if(l!="a" && l!="A" && l!="e" && l!="E" &&
l!="i" && l!="I" && l!="o" && l!="O" && l!="u" && l!="U" && l!="
"){
consonants+=l;
}
}
return consonants;
}
这个方法逐个字符遍历当前String 然后去除所有的原音或者空字符,只返回了剩下的辅音。这样我们就可以在所有的String的实例对象里或者基础类型里使用它了:
String.prototype.consonantize = consonantize;
var dg = "Danny Goodman";
var df = new String("David Flanagan");
alert(dg.consonantize());
alert(df.consonantize());
Neat, huh?(嘿嘿,呵呵,哈哈。。。。),在String类型实例里或者String基础类型中尼都可以像使用任何其他方法一样去使用这个新方法了。
总结一下:我们可以在JavaScript内建对象上的prototype上添加任何想加的方法,这跟使用我们自己定义的对象是一样的。
分享到:
- 2009-11-25 14:37
- 浏览 832
- 评论(0)
- 论坛回复 / 浏览 (0 / 1679)
- 查看更多
相关推荐
4. **类(Class)**:ES6引入了类语法糖,使得JavaScript的面向对象更加符合传统面向对象语言的写法,但实际上,这些“类”仍然基于原型实现。 ```javascript class Person { constructor(name) { this.name = ...
JavaScript是一种广泛应用于Web开发的轻量级脚本语言,它以基于对象的编程特性而闻名。基于对象编程意味着JavaScript不仅可以创建和操作对象,还可以利用现有对象的属性和方法进行编程。这种模型允许开发者以灵活的...
JavaScript是一种强大的基于对象的编程语言,它并非严格的面向对象编程(OOP)语言,而是以对象为基础。在JavaScript中,对象是由属性组成的集合,这些属性可以是基本数据类型、其他对象或是函数。JavaScript的五种...
### JavaScript基于对象编程的核心知识点 #### 一、对象的概念与特性 在JavaScript中,对象是基本的数据类型之一,它代表了现实世界中的实体,如猫、自行车或是文档中的`document`对象。对象拥有两个核心特性:...
1. 闭包(Closure)是一种JavaScript编程技术,用于实现基于类的面向对象编程。 2. 闭包可以用来模拟类的机制,并实现基于类的面向对象编程。 3. 基于闭包的JavaScript面向对象编程框架可以实现类的定义、继承和多态...
JavaScript是一种广泛...通过深入学习这本《JavaScript面向对象编程指南(第2版)》,开发者不仅能掌握JavaScript的面向对象编程基础,还能了解到实际项目中如何有效地运用这些知识,提升编程技巧和解决问题的能力。
面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它基于“对象”的概念,允许程序员创建数据结构来表示和操作现实世界中的实体。在JavaScript中,OOP主要通过构造函数、原型链、闭包以及类(ES6...
面向对象编程(Object-Oriented Programming,OOP)是一种强大的编程范式,它基于“对象”的概念,允许我们通过封装数据和方法来组织代码。在JavaScript中,面向对象编程并不是原生支持的,但它可以通过模拟类和对象...
在JavaScript中,尽管它是一种原型基于的语言而不是传统的类(class)驱动的语言,但依然可以实现强大的面向对象功能。 #### JavaScript中的对象 在JavaScript中,一切皆对象。无论是内置类型如字符串、数字还是...
JavaScript是一种基于原型的语言,这意味着它不像传统的面向对象语言(如Java或C++)那样拥有类的概念。在JavaScript中,对象是核心,一切都可以视为对象。JavaScript的对象是动态的,即可以在运行时添加或删除属性...
2. **对象和原型**:JavaScript的面向对象特性基于原型,理解原型链、构造函数和实例化过程对于深入学习至关重要。 3. **闭包**:闭包是JavaScript中的一个重要概念,它允许函数访问并操作外部作用域的变量,同时...
在JavaScript中,由于它是一种基于原型的语言,所以它的面向对象编程与传统基于类的语言如Java或C++有所不同。 接下来,书中提到的“原型”是JavaScript的一个核心概念。原型是JavaScript实现继承的基础。每个对象...
JavaScript面向对象编程是一种基于原型(Prototype)的编程范式,它是动态类型语言,允许开发者创建具有复杂特性的对象。在JavaScript中,面向对象主要通过构造函数、原型链和闭包来实现。以下是对这一主题的详细...
《JavaScript编程精解 (第一版 带书签) 中文PDF扫描版》是一本专注于JavaScript(通常简称为JS)编程语言的书籍,涵盖了ES5(ECMAScript 2016标准)的编程技术。这本书适合那些希望提升前端开发技能的读者,特别是...
尽管有一些尝试构建面向对象或基于对象的操作系统,例如Spring、Choices和Clouds等,而且许多操作系统内部使用面向对象的概念(如vnodes),但在应用编程与操作系统开发之间仍然存在越来越大的差距。 ### 总结 1. ...
2. **对象与原型**:JavaScript中的对象是基于原型的,这意味着每个对象都有一个原型链,可以继承属性和方法。`__proto__`、`Object.prototype`、`new` 关键字以及`Object.create()`都是原型机制的重要部分。 3. **...
**JavaScript编程基础** JavaScript是一种广泛应用于网页和网络应用的脚本语言,由网景公司的Brendan Eich在1995年创造。它主要负责客户端的交互,使得网页更加动态和用户友好。本课程“突破JavaScript编程实例五十...