javascript教程 - 第五部分 高級話題

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 對象 item1 的 price、shippingCost 和 quantity 屬性計算 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));

我們通過 documents.cookie 屬性來對 cookie 的數據進行存取。cookie 的格式是 "cookie的名字=cookie的值; expires=cookie的結束時間; path=路徑",而所有的 cookie 都是保存在 documents.cookie 屬性中的,它們之間使用分號 ";" 分開,所以雖然您可以單獨地設置各個 cookie,但卻要通過切分操作才能得到各個 cookie 的值,請參照下邊的示例。

【經常用到的 cookie 函數】

爲了讓您有個好的開始,下邊的三個函數分別提供了設置、刪除、獲取 cookie 的功能:

function setCookie (name, value, expires) {

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

function getCookie(name) {

var search;

search = name + "="
offset = documents.cookie.indexOf(search)
if (offset != -1) {
offset += search.length ;
end = documents.cookie.indexOf(";", offset) ;
if (end == -1)
end = documents.cookie.length;
return unescape(documents.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 或者更高版本的瀏覽器中,你可以捕捉當前瀏覽窗口中 window、layer 或 document 級別的對象的事件。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] 匹配 0 到 9 的任何數字,使用 [a-z] 匹配字母 a, b, ... , z 中的任何小寫字母,大寫字母使用 [A-Z]。
/b - 匹配一個不以英文字母或數字爲邊界的字符串。
/s - 匹配一個空白的字符 (包括空格、Tab、換行等等)。
/w - 匹配一個任何英文或者數字的字符,和 [0-9a-zA-Z] 是等同的。
由於 '*' 是特殊字符,它的作用是匹配零個或零個以上的 '*' 前邊的字符,所以如果想匹配字符 '*',需要在此字符前加一個反斜槓 '/' 字符。因此 '/*' 是匹配一個字符 '*'。你可以到 Netscape's javascript Reference 中去看一下有關正則表達式的細節。

標記可以是下邊的值:

i - 忽略大小寫。
g - 全局匹配,匹配所有符合匹配模式的字符,而不只是匹配第一個符合匹配模式的字符。
test() 方法用來比較已知的字符串,如果匹配則返回“真”值 (true)。可以看一下這個 在線示例,在這個例子中,使用了正則表達式來判斷用戶的輸入是否符合電子郵件 (Email) 地址的格式:[email protected]

動態HTML [DHTML]

動態 HTML (Dynamic HTML 或 DHTML) 給 HTML 增加了幾個新的標記,同時也增加了幾個 javascript 的對象。動態 HTML 的一個主要特性是充分利用網頁中的層 (layer) 和位置 (position)。

在這裏我們再次聲明,Netscape 和 IE 在應用上是有所不同的,Netscape 增加了支持“級聯樣式單” (Cascading style Sheets 或 CCS) 的 <LAYER> 標記用來定位網頁中的元素,而 IE 卻支持更多的樣式單,這些樣式單都是居於 World Wide Web 聯盟標準的 (可以參見第六部分的 DHTML 相關鏈接)。

【給頁面的內容定位】

雖然 Netscape 對 CSS 的支持比較有限,但是我們還是可以很容易地使用 <LAYER> 標記來創建被定位的內容。下邊的代碼在兩種瀏覽器中可以產生相同的效果:

Netscape

<layer bgcolor="#ffffcc" left=150 top=200 width=200 height=20>
顯示的文本。
</layer>

IE

<div style="background-color:#ffffcc position:absolute;
left:150px; top:200px; width:200px; height:20px;">
顯示的文本。
</div>

正如你所看到的,我們可以對被定位的內容塊 (在上邊例子中的內容塊是“顯示的文本”,也即是在 <layer>....</layer> 或 <div>....</div> 標記對之間的內容) 定義幾個特性,例如背景顏色、字體顏色等等。top 和 left 的值用來告訴瀏覽器這一塊內容在網頁中的位置,top 是距離瀏覽器窗口頂部的長度,left 則是距離瀏覽器窗口左邊框架的長度,它們的單位都是象素 (pixel)。

爲了讓代碼在兩種瀏覽器中都能實現相同的效果,我們可以使用前邊講過的方法首先探測一下瀏覽器的類型,然後再分別使用 document.writeln() 輸出適用於兩種瀏覽器的代碼參見 在線示例 。

【文檔對象模型DOM】

現在我們已經可以給網頁中的內容定位了,但我們怎樣才能熟練巧妙地使用這種方法使它成爲 DHTML 技術的一部分呢?“文檔對象模型” (簡稱 DOM) 是一個很流行的名字,它指的是在網頁中的 javascript 分級對象。DHTML 爲層與樣式單增加了一些新的對象,你可以像使用 javascript 中其它對象那樣使用這些對象。

當然,Netscape 和 IE 在 DOM 上的應用也有所不同,但是我們還是可以像上邊的例子那樣使用相應的代碼來實現相同的效果。

你可以將一個內容塊從一個地方移動 (重新定位) 到另一個地方,可以讓它從看得見變成看不見。爲了實現這些目的,你要針對不同的瀏覽器正確地處理好 javascript 對象。

讓我們重新寫一下上邊的代碼,並且在代碼中給內容塊加上名字,這樣我們才能在程序代碼中引用這些內容塊作爲對象來使用 (這其實就是 DOM 的一部分):

Netscape

<layer name="block1" bgcolor="#ffffcc" left=150 top=200 width=200 height=20>
Some text to display.
</layer>

IE

<div id="block1" style="background-color:#ffffcc position:absolute;
left:150px; top:200px; width:200px; height:20px;">
Some text to display.
</div>


現在我們將內容塊放在 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 來說,我們只要設置塊對象的 left 和 top 屬性的值就可以達到移動塊的目的,在 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 的用戶羣。或者你也可以設計多套網頁或網站,讓它們分別支持各種瀏覽器,但是這樣將會給維護網頁或網站帶來很大的麻煩,增加複雜性。

javascript教程 - 第六部分 在線資源


在線參考

Netscape DevEdge Online  http://developer.netscape.com/docs/manuals/index.html

Microsoft Scripting Technologies  http://msdn.microsoft.com/scripting/

Site Builder Network Workshop  http://www.microsoft.com/workshop/default.asp

實用示例

Developer.com  http://www.developer.com/
javascripts.com  http://www.javascripts.com/
The Web Developer's Virtual Library  http://www.stars.com/
Script Search  http://www.scriptsearch.com/
WebReference.com  http://www.webreference.com/

發佈了24 篇原創文章 · 獲贊 0 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章