首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

2.2  复合数据类型:数组和对象

复合数据类型和简单数据类型是不同的,因为它们可以保存不止一个值。复合数据类型有两种。

l    对象(object):包含任一对象(包括浏览器提供的对象)的一个引用。

l    数组(array):包含一个或多个其他的数据类型。

先看一下对象数据类型。回想一下第1章中的讨论,对象的作用是模拟现实世界中的实体。这些对象可以保存数据并提供一些属性和方法。

2.2.1  JavaScript提供的对象:String、Date和Math

这3个对象做着3种不同的事情。

l    String对象:存储一个字符串,并提供处理字符串需要的属性和方法。

l    Date对象:存储一个日期,并提供处理它的方法。

l    Math对象:不存储数据,但提供操纵数学上数据的属性和方法。

我们开始学习String对象吧。

1.String对象

前面我们通过给基本类型的字符串一些需要保存的字符串来创建它们,像下面这样:

String对象略有不同,它不止允许我们存储字符,还提供了操作和改变这些字符的方法。可以显式或隐式地创建字符串对象。

  ●   创建String对象

先看一下隐式的方法:首先声明一个新的变量,并给它赋一个基本类型的新字符串来初始化它。现在使用typeof()来确认变量myStringPrimitive中的数据就是一个基本字符串:

可是我们仍然可以对它使用String对象的方法。JavaScript会把这个字符串从基本类型简单地转换成一个临时的String对象,对它使用方法,然后再把数据类型转换成字符串。可以使用String对象的length属性来试验一下:

下面是你在浏览器窗口中看到的结果:

因此myStringPrimitive在临时转换后仍然保存着一个基本类型的字符串。我们也可以显式地创建String对象:使用new关键字和构造函数(constructor)String():

加载这个页面会显示下面的结果:

这个脚本和前一个脚本的唯一差别就在于第一行,我们创建新对象并为这个String对象提供一些字符存储:

检查length属性的结果是一样的,不管我们是显式还是隐式地创建String对象。显式与隐式地创建String对象的唯一真正的区别是,如果你要重复地使用同样的字符串,显式地创建字符串有更高的效率。显式地创建String对象还有助于防止JavaScript解释器混淆数字和字符串。

  ●   使用String对象的方法

String对象有许多方法,这里只讨论其中的2个:indexOf()和substring()方法。

你已经看到,JavaScript字符串是由字符组成的。这些字符中的每一个都有一个索引。这个索引是从0开始的,所以第一个字符的位置的索引是0,第二个是1,以此类推。方法indexOf()查找并返回子字符串起始的索引位置(lastIndexOf()方法则返回子字符串结束的位置)。举个例子,如果想让用户输入Email地址,我们能检查他们的输入中是否包含@符号。(虽然这不能确保邮件地址是合法的,但至少可以在很大程度上确保其有效,稍候我们会在本书中接触更复杂的数据校验。)

接下来,使用prompt()方法获取用户的Email地址,然后检查输入中是否包含@符号,并使用indexOf()返回@符号的索引:

如果没有发现@,在页面中会输出-1。只要在这个字符出现在输入字符串中,不管具体在任何位置,都会返回索引中它的位置,换句话说某个大于-1的数。

substring()方法使用子字符串的起始和结束位置的索引作为参数,从另一个字符串中截取一个字符串。可以不使用第2个参数来返回从第一个索引到字符串结束的所有字符串。因此要截取从第3个字符(索引2)到第6个字符(索引5)的所有字符,我们这样写:

在浏览器中会看到页面输出了llo。注意substring()方法复制了它返回的子字符串,但它没有改变原来的字符串。

处理未知的值时,substring()方法真的会用到它自己。下面是另一个例子,它同时使用了indexOf()和substring()方法:

我们在变量characterName的字符串中提取Homer,使用indexOf()查找姓的起始位置,然后给它加上9得到名的起始位置的索引(因为“Simpson,”是9个字符的长度),并把它存储在firstNameIndex中。它在substring()方法中用来提取从名的起始位置开始的所有字符——我们没有指定最后一个索引,因此这个字符串中的其余字符都会被返回。

现在来看一下Date对象。它允许存储日期并提供一些有用的日期/时间相关功能。

2.Date对象

JavaScript没有基本的日期数据类型,所以只能显式地创建Date对象。创建新的Date对象和创建String对象的方式是一样的,使用关键字new和Date构造函数。下面这行创建了一个包含当前日期和时间的Date对象:

为了创建一个存储了特定日期或时间的Date对象,可以简单地把日期或日期与时间放到括号的里面:

不同的国家使用不同的顺序来描述日期。举个例子,美国指定的日期格式是MM/DD/YY, 而欧洲的日期格式是DD/MM/YY, 在中国它们的格式是YY/MM/DD。如果使用简写的名字指定月份,那么可以以任意的顺序使用:

实际上,Date对象可以拥有许多参数:

要使用这些参数,首先需要指定年份和月份,然后使用所需要的参数,可是你不得不按顺序逐个使用且不能在它们之间选择。举例来说,可以指定年份、月份、日期和小时:

可是你不能指定年份、月份,然后指定小时:

注解    尽管我们通常认为9月(September)是第9个月份,但是JavaScript从0(1月)开始计算月份,因此月份8表示9月。

  ●   使用Date对象

Date对象拥有许多方法,可以用来获取或设置一个日期或时间。可以使用本地时间(你的计算机所在时区的时间)或者UTC(协调世界时间,也叫格林尼治标准时间)。虽然这个可能非常有用,但你要意识到在处理Date时,许多人并没有正确地设置他们的时区。下面的示例展示了其中的一些方法:

下面是你会得到的结果:

代码的这一行第一眼看起来可能有点违反常规:

JavaScript知道在一月份中没有32天,因此解释器没有把日期设置为1月32日,而是从1月1日起数了32天,所以给我们返回了2月1日。

如果需要在一个日期上增加一些天数,这是个非常方便的特性。通常如果想在一个日期上增加许多天,我们不得不考虑在不同月份中的天数,还有是不是闰年,但是如果我们使用JavaScript的日期来处理则非常地容易:

如果在提示时输入31 Dec 2003(2003年12月31日),还有1作为需要增加的天数,那么得到的结果将会是Thu Jan 1 00:00:00 UTC+0800 2004(星期四,2004年1月1日,0点0分0秒)。

注解    注意到在这个脚本的第3行中,我们使用了Math对象的Number()方法。如果不使用程序也能正常运行,但是结果将是不一样的。如果你不希望使用这个方法来转换不同的数据类型,那么有一个小技巧:使用parseInt()、parseFloat()或者Number()函数从一个可以转换成数字的字符串中减去0,那么你就会把它转换成一个数,如果给一个数上加一个空字符串'',那么就会把它转换成一个字符串,这个功能通常需要使用toString()来处理。

在代码的第4行中,我们设置日期为originalDate.getDate()返回的值加上需要增加的天数而计算出的当前日期,最后一行使用toString()方法以字符串的形式输出originalDate这个日期对象所包含的日期。如果正在使用IE 5.5以上版本或者基于Gecko的浏览器(Mozilla、Netscape 6以上版本),单独使用日期的toDateString()函数会产生一个格式化好的字符串。可以使用同样的方法获取和设置日期。如果你正在使用UTC时间,所有需要做的就是把UTC加到这个方法名上。 因此getHours()变为getUTCHours()、setMonth()变为setUTCMonth(),以此类推。也可以使用getTimezoneOffset()方法返回计算机的本地时间和UTC时间以小时计的时差。(你必须确认用户已正确设置了他们的时区,并知道不同国家之间的夏令时差别。)

注解    对于严格的日期处理,JavaScript可能并不是最合适的技术,因为你无法信任客户端的计算机都正确地设定了。但可以使用服务器端的语言来填充JavaScript脚本中的初始日期,达到同样的目的。

3.Math对象

Math对象提供了许多与数学相关的功能,例如获得一个数的平方或者产生一个随机数。Math对象和Date与String对象有2点不同:

l    不能显式地创建一个Math对象,直接使用它就可以了。

l    Math对象不存储数据,和String与Date对象不同。

可以按照下面的格式来调用Math对象的方法:

接下来我们会学习几个常用的方法(详细参考请在http://www.mozilla.org/docs/web-developer/上搜索)。在这里我们看一下舍入数字和产生随机数的方法。

  ●   舍入数字

在前面你曾看到parseInt()函数会通过消去小数点后面的一切来使一个小数变成整数(因此24.999变为24)。经常地,你会需要更多的算术方面的精确计算,举个例子,如果你正在处理财务计算,可以使用Math对象的3个舍入函数种的一个:round()、ceil()和floor()。下面是它们如何工作的。

l    round():当小数是0.5或者大于0.5的时候向上入一位。

l    ceil():始终向上舍入,因此23.75变为24, 23.25也是如此。

l    floor():始终向下舍入,因此23.75变为23, 23.25也是如此。

这里通过一个简单的示例来看看它们是如何工作的:

尽管我们使用prompt()可以从用户那里获取一个值(前面看到它会返回一个字符串),但是返回的数仍然会被当作一个数来对待。这是因为只要字符串中包含能被转换为数字的东西,舍入函数就会进行转换。

如果输入23.75,就会得到如下的结果:

如果输入-23.75,我们得到:

  ●   生成一个随机数

可以使用Math对象的random()方法,生成一个大于等于0但小于1的随机小数。通常为了利用它,你需要乘以某个数,然后再使用其中的一个舍入方法。

举个例子,为了模拟一次掷骰子事件,我们需要生成一个1~6之间的一个随机数,可以通过把随机小数乘以5,获得0~5之间的一个小数,接着使用round()方法对这个小数进行四舍五入得到一个整数。(我们不能乘以6,然后每次使用ceil()方法向上舍入,因为那样会偶然地得到0。)然后该整数位于0~5之间,所以通过加1,我们就能得到一个1~6之间的整数。这种方法不能给我们模拟一个完美的掷骰子事件,但是对于大多数的目的都足够了。下面是这段代码:

2.2.2  数组

JavaScript允许我们使用一个数组(array)来存储和访问相关的数据。一个数组有点像一行单元格(元素),每个单元格包含一个独立的数据项。一个数组可以存储JavaScript支持的任何数据类型。因此,举例来说,可以使用一个数组来处理用户从中选择的项目列表,或者一组图像坐标,或者一组图片的引用。

Array对象,类似String和Date对象,需要使用new关键字和构造函数来创建。可以在创建一个Array对象时初始化它:

或者设置它来保存一定数目的数据项:

或者只创建一个空数组:

可以通过为这些元素赋值的方式来为数组添加新的数据项:

提示    可以不使用array()构造函数;相反使用简写方式是完全有效的:

只要构造了一个数组,就可以使用中括号,通过索引和位置(它也是基于0的)来访问它的元素:

如果想循环整个数组,使用索引数来存储数据项是非常有用的,我们下面会看一下循环。

可以不使用数字索引而使用关键字来访问数据元素,像下面这样:

关键字在下面的一些情况下是非常有效的:在你可以给数据分配有用的标签,或者存储一些只有在上下文中才有效的实体的地方,如一个图像坐标列表。可是,如果它们已经使用关键字被设置了,那么你不能使用索引数来访问实体(在一些其他的语言中是可以的,如PHP)。也可以使用变量作为索引。我们使用变量(分别保存一个字符串和一个数)代替文本值,改写一下前面的示例:

让我们把已讨论过的数组和Math对象的知识应用到一个示例中。编写一个简单的脚本,它随机地选取一个广告横幅以显示到网页的顶部。

使用一个Array对象来保存一些图片的源文件名:

接着我们需要6个具有对应名字的图片,放在和HTML网页相同的文件夹里。可以使用你自己的图片或者从网站http://www.beginningjavascript.com上下载我提供的。

接下来初始化一个新的变量randomImageIndex,使用它来产生一个随机数。在这里使用与前面曾经用过的产生一个随机掷骰子数相同的方法,但是不用在结果上加1,因为我们需要产生一个0~6之间的随机数:

然后使用document.write()把随机选择的图片写到网页中。下面是它完整的代码:

上面就是与之相关的所有东西了。使广告横幅不断地变化比每次访问网页的时候都显示同样的横幅广告更加容易引起访问者的注意,当然,它还会给访问者一个印象,即这个站点在经常地更新。

数组对象的方法和属性

数组对象最常用的一个属性就是length属性,它返回比数组中最后一个数组项索引大1的索引。举个例子,如果你正在处理一个数组,它拥有索引为0、1、2、3的元素,length属性就是4。如果想添加另外的元素,知道这一点是非常有用的。

Array对象提供了许多方法用来操作数组,包括从数组中截取一部分元素的方法,或者把两个数组连接到一起。下面我们来看连接、截取和排序的方法。

  ●   截取数组的一段

slice()方法对于一个Array对象就如同substring()方法对于一个String对象。只要简单地告诉这个方法你想要截取哪些元素。这是非常有用的,譬如说当你想要一个使用URL传递的信息片段的时候。

slice()方法拥有2个参数:片段中第一个元素的索引,它包含在这个片段中;最后一个元素的索引,片段中不会包含它。为了访问一个总共包含5个值的数组中的第2、第3和第4个值,我们使用索引1和4:

这个新数组存储数字是从0开始的,因此片段的索引0、1和2会给我们下面的结果:

最初的数组并未受影响,但是如果需要,可以通过设置它为slice()方法返回的结果,重写变量中的这个数组对象:

  ●   连接2个数组

Array对象的concat()方法允许连接数组。可以使用这个方法把2个或多个数组连接到一起,每个新数组在前面数组结束的地方开始。这里,我们连接了3个数组:arrayOne、arrayTwo和arrayThree:

这个新数组joinedArray拥有12个数据项。这个数组中的数据项和它们在以前的数组中是一样的;它们只是被简单地连接到一起。原来的数组仍然没有改变。

  ●   数组和字符串之间的相互转换

当你想循环元素或选取某些元素的时候,把数据放到数组里是非常便利的。可是,当你需要把数据传送到其他地方的时候,把数据转换成字符串可能是个非常好的主意。可以通过循环数组并把每个元素的值加到一个字符串里来实现。可是没有必要那么去做,因为Array对象有一个叫join()的方法可以用来完成这个功能。这个方法需要一个字符串作为参数。这个字符串会被添加到每个元素的中间。

作为结果的字符串lineUp的值是"John, Paul, George, Ringo"。与join()相反的操作是split(),这个方法可以把字符串转换为数组。

  ●   数组排序

sort()方法允许把数组中的数据项按字母或者数字顺序进行排序:

数据项会按下面的方式排序:

可是,如果把其中的一个字母小写,例如Apple中的A字母,那么你会得到一个完全不同的结果。这个排序是按照严格的数学顺序——ASCII码中的字符编号进行的,而不是像人那样会按照单词进行排序。

如果想改变已经排序好的元素的显示顺序,可以使用reverse()方法来把字母表中的最后的字母作为第一个元素来显示:

结果序列现在是按原序列的反序进行排列的:

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论