JavaScript教程 - 第五部分 高级话题

来源:百度文库 编辑:神马文学网 时间:2024/04/27 18:27:03
JavaScript教程 - 第五部分 高级话题

来源:

[正文]

在这一章中,我们将大致的学习一下一些 JavaScript 中比较高级的话题,在此我们只是通过一些例子大致学习,而不进行深入探讨。

创建你自己的对象

正如您所看到的,JavaScript 提供了很多网页组件和数据的对象及对象类型。但是,您的目光不能仅仅限于这些,您可以根据自己的需要创建自己的对象、属性和方法,这是很有用的,比如说您需要一个比较复杂的数据结构的时候,您就需要这样做。

在创建一个新的对象之前,您首先要创建一个数据结构。这些工作都在一个函数里边处理,在该函数中定义您的对象的属性(可以给这些属性设置初始值),然后你就可以创建居于此对象的方法了。

【构造对象函数】

每一个对象都需要一个构造对象函数,我们通过使用 new 关键字调用此函数来创建一个新的对象实例。这类函数定义了对象的属性,同时给这些属性设置初始值。您还可以在此类函数中声明对象的方法。

下边就是使用构造对象函数的一个例子,在这个函数中定义了一个新的对象 Product,此对象定义了每一个产品的基本属性:

function Product(name, num, price, shipping, quantity) {

this.name = name;
this.catalogNumber = num;
this.price = price;
this.shippingCost = shipping;
this.quantity = quantity;
}

注意关键字 this,它指向被创建的对象。您可以像下边那样创建新的 Product 对象实例:

var item1 = new Product("blender", "9003-2", 24.95, 2.50, 2);
var item2 = new Product("juicer", "9117-1", 49.95, 5.00, 1);

你还可以像访问其它对象的属性那样访问 Product 对象的属性:

var total = (item1.price + item1.shippingCost) * item1.quantity;


【定义方法】

上边的例子中通过访问 Product 对象 item1priceshippingCostquantity 属性计算 item1 的总价值,如果我们需要经常计算总价值,那么像上边那样用起来就很不方便,不过不用担心,我们可以为计算总价值创建一个方法,很简单,只要在构造对象函数中添加一行代码:“this.totalCost = totalCost;”,然后在构造对象函数的后边定义一个名为 totalCost 的函数:

function Product(name, num, price, shipping, quantity) {

this.name = name;
this.catalogNumber = num;
this.price = price;
this.shippingCost = shipping;
this.quantity = quantity;
this.totalCost = totalCost;
}

function totalCost() {

return ((this.price + this.shippingCost) * this.quantity);
}

注意在构造对象函数中定义该对象方法的格式:this.methodName = functionName,这里的方法名和函数名并不需要使用相同的名字,我们这里是为了看得清楚才使用相同的名字 totalCost 的。现在我们就可以使用此对象的方法了:

var total = item1.totalCost();

如果想了解如何构建和使用自定义对象,可以看一下这个 在线示例 ,这个例子中定义了一个简单的购物车,我们构建的对象名为 ShoppingCart,同时还给这个对象定义了增加和删除产品项的方法。

Cookies

使用 cookie,您可以将一些数据信息保存在客户端用户的机器中,而在以后用户浏览您的网页的时候再调出来使用。通常我们使用 cookie 保存一些数据、登陆帐号等。

创建一个 cookie 需要用到下边的信息:

  • cookie 的名字=cookie的值 - 这个字符串表示 cookie 的数据,请看下边;
  • 结束时间 - 您的 cookie 在客户端保留的时间,即是截止时间,如果当天的时间大于这个日期时间,那么客户端用户的机器将会删除这个 cookie
  • 域 (Domain) 和路径 (Path) - 这些是用于安全方面的,默认的情况下,域的值是服务器主机的域名,路径是当前这个设置 cookie 的页面在主机中相对于域名的路径 (这样就只有在相同路径下的那些页面可以使用此 cookie 了);
  • 安全性 - 如果这个安全性标志被设置成 true 的话,那么 cookie 将会在一个安全的方式 (SSL 连接) 下发送到客户端。

通常,您只需要设置前两项 "cookie 的名字=cookie 的值" 和 "结束时间" 即可。在设置结束时间的时候,您可以使用 Date 对象,但要注意格式,单位是毫秒。下边就是一个例子,在这个例子中,"结束时间" 被设置成从当前时间算起过任意多天 (此例设置的 "结束时间" 是 7 天后):

var days = 7;
var expdate = new Date();
expdate.setTime (expdate.getTime() + (86400 * 1000 * days));

我们通过 document.cookie 属性来对 cookie 的数据进行存取。cookie 的格式是 "cookie的名字=cookie的值; expires=cookie的结束时间; path=路径",而所有的 cookie 都是保存在 document.cookie 属性中的,它们之间使用分号 ";" 分开,所以虽然您可以单独地设置各个 cookie,但却要通过切分操作才能得到各个 cookie 的值,请参照下边的示例。

【经常用到的 cookie 函数】

为了让您有个好的开始,下边的三个函数分别提供了设置、删除、获取 cookie 的功能:

function setCookie (name, value, expires) {

document.cookie = name + "=" + escape(value) +
"; expires=" + expires.toGMTString() + "; path=/";
}

function getCookie(name) {

var search;

search = name + "="
offset = document.cookie.indexOf(search)
if (offset != -1) {
offset += search.length ;
end = document.cookie.indexOf(";", offset) ;
if (end == -1)
end = document.cookie.length;
return unescape(document.cookie.substring(offset, end));
}
else
return "";
}

function deleteCookie(name) {

var expdate = new Date();
expdate.setTime(expdate.getTime() - (86400 * 1000 * 1));
setCookie(name, "", expdate);
}

escape()unescape()JavaScript 的内建函数,它们用来将一些特殊字符转换成十六进制代码。通常情况下,cookie 中的名字、值都不能包含任何空格、逗号或分号。使用这两个函数可以将这一类的字符转换成合法的可供 cookie 使用的十六进制字符。

删除所有您不再使用的 cookie 是一个很好的习惯,因为客户端会限制您可以存储的 cookie 个数 (对于 Netscape 浏览器来说:每一个主机/域最多是 20 个 cookie,总共可以存储 300 个)。上边的删除 cookie 的函数将 cookie 的结束时间设置成前一天的时间,这样就可以达到删除的目的了。

看看这个 在线示例 就知道上边函数的用法了。

注意:以下的部分使用 JavaScript 1.2 ,而且只运用于 Netscape 和 IE version 4.0 或者更高版本。

事件捕捉

我们在这个教程中已经学过了事件句柄 (event handler),Internet Explorer 浏览器几乎为每一个 HTML 标记提供了事件句柄,而 Netscape 却有所不同,虽然它也为很多 HTML 标记提供了事件句柄,但是一些事件必须通过别的方法来捕捉。

【在 Netscape 中捕捉事件】

在 Netscape 4 或者更高版本的浏览器中,你可以捕捉当前浏览窗口中 windowlayerdocument 级别的对象的事件。captureEvent() 方法可以完成此操作, 此方法指定想要捕捉的事件,然后在通过编写函数来处理此事件句柄。

下边的例子中我们通知 window 对象捕捉鼠标点击的事件:

window.captureEvents(Event.CLICK);
window.document.onClick = myClick;

function myClick(even) {
...
}

请注意,我们在到 captureEvents() 方法中传送参数 Event.CLICK。这个事件对象 Event 包含了与事件有关的信息。而 Event.CLICK 是一个指向通常事件类型的对象实例,其它一些事件类型如下:

  • CLICK - 当鼠标点击的时候触发此事件
  • MOUSEDOWN - 当鼠标被按下的时候触发此事件
  • MOUSEUP - 当鼠标被松开的时候触发此事件
  • MOUSEMOVE - 当鼠标移动的时候触发此事件
  • KEYPRESS - 当从键盘输入的时候触发此事件
  • KEYDOWN - 当按下键盘的时候触发此事件
  • KEYUP - 当松开键盘的时候触发此事件

如果想捕捉更多的事件,您必须使用逻辑或运算符“|”来分割各个事件类型,如下边的代码所示:

window.captureEvents(Event.MOUSEDOWN | Event.KEYDOWN);
window.document.onMouseDown = myMouseDown;
window.document.onKeyDown = myKeyDown;

我们将 event 对象传递给事先安排好的事件句柄 (即此事件的处理函数),这个对象包含了一些通常的时间数据,例如它的类型等等。

【Internet Explorer 中的事件】

在 Internet Explorer 中不需要传递 event 对象,因为通常的时间对象都是 window 对象的一个属性。不幸的是,IE 的这些属性和 Netscape 的却不尽相同。

【编写具有兼容性的代码】

幸运的是,这两种浏览器之间还是有共同的代码可以使用的,最重要的是能够使用代码将两种浏览器区分开来。你可以尝试使用一些对象来试探浏览器的类型,例如,你可以使用 document.layers 对象来试探,这个对象是 Netscape 支持的对象,而相对应的 document.all 对象则是只有 IE 才支持的对象, Netscape 则不支持:

if (document.layers) {

// 在此处编写 Netscape 支持的代码
...
}

else if (document.all) {

// 在此处编写 IE 支持的代码
...
}

else {

// 在此处编写 Netscape 和 IE 都支持的代码
...
}

如果所试探的对象不存在 (即当前的浏览器不支持),它的值为空 (null) ,这就促使 if 表达式的值为“假” (false)。这种方法也可以用来防止这两种浏览器不支持该对象的老版本试图执行这些代码。

看一下这个 在线示例 将会对您又很大的帮助。例子中的代码可以在 Netscape 和 IE 两种浏览器中实现相同的效果。

正则表达式

正则表达式是用于模式匹配的,它提供了强大的字符串替换、转换以及搜索功能。

Netscape 和 IE 在正则表达式对象的使用上有细微的不同,但是下边的代码却是通用的:

var myRE = /匹配模式/标记;

匹配模式的过程被看成是逐字匹配的,同时使用正则表达式还能匹配特殊字符或特殊格式的字符串 (左边的符号是匹配模式中使用的特殊格式):

  • a* - 匹配零个或零个以上的字符 a
  • a+ - 匹配一个或一个以上的字符 a
  • . - 匹配任何字符。
  • a|b - 匹配字符 a 或者 b
  • a{ n } - 匹配 n 个连续的字符 a
  • [abc] - 匹配一个字符,这个字符是方括号“[]”中的任何一个字符,使用 [0-9] 匹配 09 的任何数字,使用 [a-z] 匹配字母 a, b, ... , z 中的任何小写字母,大写字母使用 [A-Z]
  • \b - 匹配一个不以英文字母或数字为边界的字符串。
  • \s - 匹配一个空白的字符 (包括空格、Tab、换行等等)。
  • \w - 匹配一个任何英文或者数字的字符,和 [0-9a-zA-Z] 是等同的。

由于 '*' 是特殊字符,它的作用是匹配零个或零个以上的 '*' 前边的字符,所以如果想匹配字符 '*',需要在此字符前加一个反斜杠 '\' 字符。因此 '\*' 是匹配一个字符 '*'。你可以到 Netscape's JavaScript Reference 中去看一下有关正则表达式的细节。

标记可以是下边的值:

  • i - 忽略大小写。
  • g - 全局匹配,匹配所有符合匹配模式的字符,而不只是匹配第一个符合匹配模式的字符。

test() 方法用来比较已知的字符串,如果匹配则返回“真”值 (true)。可以看一下这个 在线示例,在这个例子中,使用了正则表达式来判断用户的输入是否符合电子邮件 (Email) 地址的格式:userid@domain.net

动态HTML [DHTML]

动态 HTML (Dynamic HTMLDHTML) 给 HTML 增加了几个新的标记,同时也增加了几个 JavaScript 的对象。动态 HTML 的一个主要特性是充分利用网页中的层 (layer) 和位置 (position)。

在这里我们再次声明,Netscape 和 IE 在应用上是有所不同的,Netscape 增加了支持“级联样式单” (Cascading Style SheetsCCS) 的 标记用来定位网页中的元素,而 IE 却支持更多的样式单,这些样式单都是居于 World Wide Web 联盟标准的 (可以参见第六部分的 DHTML 相关链接)。

【给页面的内容定位】

虽然 NetscapeCSS 的支持比较有限,但是我们还是可以很容易地使用 标记来创建被定位的内容。下边的代码在两种浏览器中可以产生相同的效果:

Netscape


显示的文本。

IE


显示的文本。

正如你所看到的,我们可以对被定位的内容块 (在上边例子中的内容块是“显示的文本”,也即是在 ....

....
标记对之间的内容) 定义几个特性,例如背景颜色、字体颜色等等。top left 的值用来告诉浏览器这一块内容在网页中的位置,top 是距离浏览器窗口顶部的长度,left 则是距离浏览器窗口左边框架的长度,它们的单位都是象素 (pixel)。

为了让代码在两种浏览器中都能实现相同的效果,我们可以使用前边讲过的方法首先探测一下浏览器的类型,然后再分别使用 document.writeln() 输出适用于两种浏览器的代码参见 在线示例 。

【文档对象模型DOM

现在我们已经可以给网页中的内容定位了,但我们怎样才能熟练巧妙地使用这种方法使它成为 DHTML 技术的一部分呢?“文档对象模型” (简称 DOM) 是一个很流行的名字,它指的是在网页中的 JavaScript 分级对象。DHTML 为层与样式单增加了一些新的对象,你可以像使用 JavaScript 中其它对象那样使用这些对象。

当然,Netscape 和 IE 在 DOM 上的应用也有所不同,但是我们还是可以像上边的例子那样使用相应的代码来实现相同的效果。

你可以将一个内容块从一个地方移动 (重新定位) 到另一个地方,可以让它从看得见变成看不见。为了实现这些目的,你要针对不同的浏览器正确地处理好 JavaScript 对象。

让我们重新写一下上边的代码,并且在代码中给内容块加上名字,这样我们才能在程序代码中引用这些内容块作为对象来使用 (这其实就是 DOM 的一部分):

Netscape


Some text to display.

IE


Some text to display.

现在我们将内容块放在 JavaScript 函数中当作对象来使用,同时返回此内容块对象本身:

function getBlock(name) {

// For Netscape.

if (document.layers)
return(document.layers[name]);

// For IE.

else if (document.all) {
layer = eval('document.all.' + name + '.style');
return(layer);
}

// 以上都不是,则返回 null.

else
return(null);
}

正如你所看到的,Netscape 使用 document.layers 数组来存储块对象,而 IE 则是创建名为 document.all.块名字.style 的对象来表示块。上边的函数返回了块对象,于是我们就可以使用这个返回值来访问块的属性或执行块的方法了。

现在让我们来看一下 在线示例 是如何移动一个块的。对于 Netscape 来说,我们只要设置块对象的 lefttop 属性的值就可以达到移动块的目的,在 IE 中则是使用 pixelLeft pixelTop 属性。在下边的函数 moveBlockBy 中将会改变这些属性的值:

function moveBlockBy(x, y) {

var block = getBlock("block1");

if (document.layers) {
block.left += x;
block.top += y;
}
else if (document.all) {
block.pixelLeft += x;
block.pixelTop += y;
}
}

参数 x 和 y 是块在水平和垂直方向上的移动增量。

【处理浏览器的兼容性问题】

正如你所看到的,两种浏览器在 DOM 上的运用也有很多不同之处,这样就给你在网页中实现 动态 HTML 效果带来了挑战,所以在编写代码的时候应该尽量避免使用不兼容的属性、方法等。

当然,你也可以只设计谋一种浏览器的代码,例如只设计 IE 浏览器可执行的代码,而不考虑 Netscape,但是这样你就将会失去 Netscape 的用户群。或者你也可以设计多套网页或网站,让它们分别支持各种浏览器,但是这样将会给维护网页或网站带来很大的麻烦,增加复杂性。