對象化編程
JavaScript 是使用“對象化編程”的,或者叫“面向對象編程”的。所謂“對象化編程”,意思是把 JavaScript 能涉及的範圍劃分成大大小小的對象,對象下面還繼續劃分對象直至非常詳細為止,所有的編程都以對象為出發點,基於對象。小到一個變量,大到網頁文檔、窗口甚至屏幕,都是對象。這一章將“面向對象”講述 JavaScript 的運行情況。
對象的基本知識
對象是可以從 JavaScript“勢力範圍”中劃分出來的一小塊,可以是一段文字、一幅圖片、一個表單(Form)等等。每個對象有它自己的屬性、方法和事件。對象的屬性是反映該對象某些特定的性質的,例如:字符串的長度、圖像的長寬、文字框(Textbox)裏的文字等等;對象的方法能對該對象做一些事情,例如,表單的“提交”(Submit),窗口的“滾動”(Scrolling)等等;而對象的事件就能響應發生在對象上的事情,例如提交表單產生表單的“提交事件”,點擊連接產生的“點擊事件”。不是所有的對象都有以上三個性質,有些沒有事件,有些只有屬性。引用對象的任一“性質”用“<對象名>.<性質名>”這種方法。
基本對象
現在我們要複習以上學過的內容了——把一些數據類型用對象的角度重新學習一下。
Number “數字”對象。這個對象用得很少,作者就一次也沒有見過。不過屬於“Number”的對象,也就是“變量”就多了。
屬性
MAX_VALUE 用法:Number.MAX_VALUE;返回“最大值”。
MIN_VALUE 用法:Number.MIN_VALUE;返回“最小值”。
NaN 用法:Number.NaN 或 NaN;返回“NaN”。“NaN”(不是數值)在很早就介紹過了。
NEGATIVE_INFINITY 用法:Number.NEGATIVE_INFINITY;返回:負無窮大,比“最小值”還小的值。
POSITIVE_INFINITY 用法:Number.POSITIVE_INFINITY;返回:正無窮大,比“最大值”還大的值。
方法
toString() 用法:<數值變量>.toString();返回:字符串形式的數值。如:若 a == 123;則 a.toString() == '123'。
String 字符串對象。聲明一個字符串對象最簡單、快捷、有效、常用的方法就是直接賦值。
屬性
length 用法:<字符串對象>.length;返回該字符串的長度。
方法
charAt() 用法:<字符串對象>.charAt(<位置>);返回該字符串位於第<位置>位的單個字符。注意:字符串中的一個字符是第 0 位的,第二個才是第 1 位的,最後一個字符是第 length - 1 位的。
charCodeAt() 用法:<字符串對象>.charCodeAt(<位置>);返回該字符串位於第<位置>位的單個字符的 ASCII 碼。
fromCharCode() 用法:String.fromCharCode(a, b, c...);返回一個字符串,該字符串每個字符的 ASCII 碼由 a, b, c... 等來確定。
indexOf() 用法:<字符串對象>.indexOf(<另一個字符串對象>[, <起始位置>]);該方法從<字符串對象>中查找<另一個字符串對象>(如果給出<起始位置>就忽略之前的位置),如果找到了,就返回它的位置,沒有找到就返回“-1”。所有的“位置”都是從零開始的。
lastIndexOf() 用法:<字符串對象>.lastIndexOf(<另一個字符串對象>[, <起始位置>]);跟 indexOf() 相似,不過是從後邊開始找。
split() 用法:<字符串對象>.split(<分隔符字符>);返回一個數組,該數組是從<字符串對象>中分離開來的,<分隔符字符>決定了分離的地方,它本身不會包含在所返回的數組中。例如:'1&2&345&678'.split('&')返回數組:1,2,345,678。關於數組,我們等一下就討論。
substring() 用法:<字符串對象>.substring(<始>[, <終>]);返回原字符串的子字符串,該字符串是原字符串從<始>位置到<終>位置的前一位置的一段。<終> - <始> = 返回字符串的長度(length)。如果沒有指定<終>或指定得超過字符串長度,則子字符串從<始>位置一直取到原字符串尾。如果所指定的位置不能返回字符串,則返回空字符串。
substr() 用法:<字符串對象>.substr(<始>[, <長>]);返回原字符串的子字符串,該字符串是原字符串從<始>位置開始,長度為<長>的一段。如果沒有指定<長>或指定得超過字符串長度,則子字符串從<始>位置一直取到原字符串尾。如果所指定的位置不能返回字符串,則返回空字符串。
toLowerCase() 用法:<字符串對象>.toLowerCase();返回把原字符串所有大寫字母都變成小寫的字符串。
toUpperCase() 用法:<字符串對象>.toUpperCase();返回把原字符串所有小寫字母都變成大寫的字符串。
Array 數組對象。數組對象是一個對象的集合,裏邊的對象可以是不同類型的。數組的每一個成員對象都有一個“下標”,用來表示它在數組中的位置(既然是“位置”,就也是從零開始的啦)。
數組的定義方法:
var <數組名> = new Array();
這樣就定義了一個空數組。以後要添加數組元素,就用:
<數組名>[<下標>] = ...;
注意這裏的方括號不是“可以省略”的意思,數組的下標表示方法就是用方括號括起來。
如果想在定義數組的時候直接初始化數據,請用:
var <數組名> = new Array(<元素1>, <元素2>, <元素3>...);
例如,var myArray = new Array(1, 4.5, 'Hi'); 定義了一個數組 myArray,裏邊的元素是:myArray[0] == 1; myArray[1] == 4.5; myArray[2] == 'Hi'。
但是,如果元素列表中只有一個元素,而這個元素又是一個正整數的話,這將定義一個包含<正整數>個空元素的數組。
注意:JavaScript只有一維數組!千萬不要用“Array(3,4)”這種愚蠢的方法來定義 4 x 5 的二維數組,或者用“myArray[2,3]”這種方法來返回“二維數組”中的元素。任意“myArray[...,3]”這種形式的調用其實只返回了“myArray[3]”。要使用多維數組,請用這種虛擬法:
var myArray = new Array(new Array(), new Array(), new Array(), ...);
其實這是一個一維數組,裏邊的每一個元素又是一個數組。調用這個“二維數組”的元素時:myArray[2][3] = ...;
屬性
length 用法:<數組對象>.length;返回:數組的長度,即數組裏有多少個元素。它等於數組裏最後一個元素的下標加一。所以,想添加一個元素,只需要:myArray[myArray.length] = ...。
方法
join() 用法:<數組對象>.join(<分隔符>);返回一個字符串,該字符串把數組中的各個元素串起來,用<分隔符>置於元素與元素之間。這個方法不影響數組原本的內容。
reverse() 用法:<數組對象>.reverse();使數組中的元素順序反過來。如果對數組[1, 2, 3]使用這個方法,它將使數組變成:[3, 2, 1]。
slice() 用法:<數組對象>.slice(<始>[, <終>]);返回一個數組,該數組是原數組的子集,始於<始>,終於<終>。如果不給出<終>,則子集一直取到原數組的結尾。
sort() 用法:<數組對象>.sort([<方法函數>]);使數組中的元素按照一定的順序排列。如果不指定<方法函數>,則按字母順序排列。在這種情況下,80 是比 9 排得前的。如果指定<方法函數>,則按<方法函數>所指定的排序方法排序。<方法函數>比較難講述,這裏只將一些有用的<方法函數>介紹給大家。
按升序排列數字:
function sortMethod(a, b) {
return a - b;
}
myArray.sort(sortMethod);
按降序排列數字:把上面的“a - b”該成“b - a”。
有關函數,請看下面。
Math “數學”對象,提供對數據的數學計算。下面所提到的屬性和方法,不再詳細說明“用法”,大家在使用的時候記住用“Math.<名>”這種格式。
屬性
E 返回常數 e (2.718281828...)。
LN2 返回 2 的自然對數 (ln 2)。
LN10 返回 10 的自然對數 (ln 10)。
LOG2E 返回以 2 為低的 e 的對數 (log2e)。
LOG10E 返回以 10 為低的 e 的對數 (log10e)。
PI 返回π(3.1415926535...)。
SQRT1_2 返回 1/2 的平方根。
SQRT2 返回 2 的平方根。
方法
abs(x) 返回 x 的絕對值。
acos(x) 返回 x 的反餘弦值(餘弦值等於 x 的角度),用弧度表示。
asin(x) 返回 x 的反正弦值。
atan(x) 返回 x 的反正切值。
atan2(x, y) 返回複平面內點(x, y)對應的複數的幅角,用弧度表示,其值在 -π 到 π 之間。
ceil(x) 返回大於等於 x 的最小整數。
cos(x) 返回 x 的餘弦。
exp(x) 返回 e 的 x 次冪 (ex)。
floor(x) 返回小於等於 x 的最大整數。
log(x) 返回 x 的自然對數 (ln x)。
max(a, b) 返回 a, b 中較大的數。
min(a, b) 返回 a, b 中較小的數。
pow(n, m) 返回 n 的 m 次冪 (nm)。
random() 返回大於 0 小於 1 的一個隨機數。
round(x) 返回 x 四舍五入後的值。
sin(x) 返回 x 的正弦。
sqrt(x) 返回 x 的平方根。
tan(x) 返回 x 的正切。
Date 日期對象。這個對象可以儲存任意一個日期,從 0001 年到 9999 年,並且可以精確到毫秒數(1/1000 秒)。在內部,日期對象是一個整數,它是從 1970 年 1 月 1 日零時正開始計算到日期對象所指的日期的毫秒數。如果所指日期比 1970 年早,則它是一個負數。所有日期時間,如果不指定時區,都采用“UTC”(世界時)時區,它與“GMT”(格林威治時間)在數值上是一樣的。
定義一個日期對象:
var d = new Date;
這個方法使 d 成為日期對象,並且已有初始值:當前時間。如果要自定初始值,可以用:
var d = new Date(99, 10, 1); //99 年 10 月 1 日
var d = new Date('Oct 1, 1999'); //99 年 10 月 1 日
等等方法。最好的方法就是用下面介紹的“方法”來嚴格的定義時間。
方法
以下有很多“g/set[UTC]XXX”這樣的方法,它表示既有“getXXX”方法,又有“setXXX”方法。“get”是獲得某個數值,而“set”是設定某個數值。如果帶有“UTC”字母,則表示獲得/設定的數值是基於 UTC 時間的,沒有則表示基於本地時間或瀏覽期默認時間的。
如無說明,方法的使用格式為:“<對象>.<方法>”,下同。
g/set[UTC]FullYear() 返回/設置年份,用四位數表示。如果使用“x.set[UTC]FullYear(99)”,則年份被設定為 0099 年。
g/set[UTC]Year() 返回/設置年份,用兩位數表示。設定的時候瀏覽器自動加上“19”開頭,故使用“x.set[UTC]Year(00)”把年份設定為 1900 年。
g/set[UTC]Month() 返回/設置月份。
g/set[UTC]Date() 返回/設置日期。
g/set[UTC]Day() 返回/設置星期,0 表示星期天。
g/set[UTC]Hours() 返回/設置小時數,24小時制。
g/set[UTC]Minutes() 返回/設置分鐘數。
g/set[UTC]Seconds() 返回/設置秒鐘數。
g/set[UTC]Milliseconds() 返回/設置毫秒數。
g/setTime() 返回/設置時間,該時間就是日期對象的內部處理方法:從 1970 年 1 月 1 日零時正開始計算到日期對象所指的日期的毫秒數。如果要使某日期對象所指的時間推遲 1 小時,就用:“x.setTime(x.getTime() + 60 * 60 * 1000);”(一小時 60 分,一分 60 秒,一秒 1000 毫秒)。
getTimezoneOffset() 返回日期對象采用的時區與格林威治時間所差的分鐘數。在格林威治東方的市區,該值為負,例如:中國時區(GMT+0800)返回“-480”。
toString() 返回一個字符串,描述日期對象所指的日期。這個字符串的格式類似於:“Fri Jul 21 15:43:46 UTC+0800 2000”。
toLocaleString() 返回一個字符串,描述日期對象所指的日期,用本地時間表示格式。如:“2000-07-21 15:43:46”。
toGMTString() 返回一個字符串,描述日期對象所指的日期,用 GMT 格式。
toUTCString() 返回一個字符串,描述日期對象所指的日期,用 UTC 格式。
parse() 用法:Date.parse(<日期對象>);返回該日期對象的內部表達方式。
全局對象
全局對象從不現形,它可以說是虛擬出來的,目的在於把全局函數“對象化”。在 Microsoft JScript 語言參考中,它叫做“Global 對象”,但是引用它的方法和屬性從來不用“Global.xxx”(況且這樣做會出錯),而直接用“xxx”。
屬性
NaN 一早就說過了。
方法
eval() 把括號內的字符串當作標准語句或表達式來運行。
isFinite() 如果括號內的數字是“有限”的(介於 Number.MIN_VALUE 和 Number.MAX_VALUE 之間)就返回 true;否則返回 false。
isNaN() 如果括號內的值是“NaN”則返回 true 否則返回 false。
parseInt() 返回把括號內的內容轉換成整數之後的值。如果括號內是字符串,則字符串開頭的數字部分被轉換成整數,如果以字母開頭,則返回“NaN”。
parseFloat() 返回把括號內的字符串轉換成浮點數之後的值,字符串開頭的數字部分被轉換成浮點數,如果以字母開頭,則返回“NaN”。
toString() 用法:<對象>.toString();把對象轉換成字符串。如果在括號中指定一個數值,則轉換過程中所有數值轉換成特定進制。
escape() 返回括號中的字符串經過編碼後的新字符串。該編碼應用於 URL,也就是把空格寫成“%20”這種格式。“+”不被編碼,如果要“+”也被編碼,請用:escape('...', 1)。
unescape() 是 escape() 的反過程。解編括號中字符串成為一般字符串。
函數
函數的定義
所謂“函數”,是有返回值的對象或對象的方法。
函數的種類
常見的函數有:構造函數,如 Array(),能構造一個數組;全局函數,即全局對象裏的方法;自定義函數;等等。
自定義函數
定義函數用以下語句:
function 函數名([參數集]) {
...
[return[ <值>];]
...
}
其中,用在 function 之後和函數結尾的大括號是不能省去的,就算整個函數只有一句。
函數名與變量名有一樣的起名規定,也就是只包含字母數字下劃線、字母排頭、不能與保留字重複等。
參數集可有可無,但括號就一定要有。
參數 是函數外部向函數內部傳遞信息的橋梁,例如,想叫一個函數返回 3 的立方,你就要讓函數知道“3”這個數值,這時候就要有一個變量來接收數值,這種變量叫做參數。
參數集是一個或多個用逗號分隔開來的參數的集合,如:a, b, c。
函數的內部有一至多行語句,這些語句並不會立即執行,而只當有其它程序調用它時才執行。這些語句中可能包含“return”語句。在執行一個函數的時候,碰到 return 語句,函數立刻停止執行,並返回到調用它的程序中。如果“return”後帶有<值>,則退出函數的同時返回該值。
在函數的內部,參數可以直接當作變量來使用,並可以用 var 語句來新建一些變量,但是這些變量都不能被函數外部的過程調用。要使函數內部的信息能被外部調用,要麼使用“return”返回值,要麼使用全局變量。
全局變量 在 Script 的“根部”(非函數內部)的“var”語句所定義的變量就是全局變量,它能在整個過程的任意地方被調用、更改。
例
function addAll(a, b, c) {
return a + b + c;
}
var total = addAll(3, 4, 5);
這個例子建立了一個叫“addAll”的函數,它有 3 個參數:a, b, c,作用是返回三個數相加的結果。在函數外部,利用“var total = addAll(3, 4, 5);”接收函數的返回值。
更多的時候,函數是沒有返回值的,這種函數在一些比較強調嚴格的語言中是叫做“過程”的,例如 Basic 類語言的“Sub”、Pascal 語言的“procedure”。
屬性
arguments 一個數組,反映外部程序調用函數時指定的參數。用法:直接在函數內部調用“arguments”。 文檔對象
現在我們將開始討論更“實際”的話題——文檔對象(DOM)。文檔對象是指在網頁文檔裏劃分出來的對象。在 JavaScript 能夠涉及的範圍內有如下幾個“大”對象:window, document, location, navigator, screen, history 等。下面是一個文檔對象樹,你可以看到對象下包含對象的“壯觀”情景。要引用某個對象,就要把父級的對象都列出來。例如,要引用某表單“applicationForm”的某文字框“customerName”,就要用“document.applicationForm.customerName”。
下表中有些對象是全小寫的,有些是以大寫字母開頭的。以大寫字母開頭的對象表示,引用該對象不使用下表列出的名字,而直接用對象的“名字”(Id 或 Name,下面有講解),或用它所屬的對象數組指定。
這裏我們不准備講解對象的“事件”,雖然我們也會列出對象所能響應的事件。我們將會在下一章“事件處理”中講解事件。
navigator
screen
window
history
location
frames[]; Frame
document
anchors[]; links[]; Link
applets[]
embeds[]
forms[]; Form
Button
Checkbox
elements[]; Element
Hidden
Password
Radio
Reset
Select
options[]; Option
Submit
Text
Textarea
images[]; Image
瀏覽器對象
屏幕對象
窗口對象
曆史對象
地址對象
框架對象
文檔對象
連接對象
Java小程序對象
插件對象
表單對象
按鈕對象
複選框對象
表單元素對象
隱藏對象
密碼輸入區對象
單選域對象
重置按鈕對象
選擇區(下拉菜單、列表)對象
選擇項對象
提交按鈕對象
文本框對象
多行文本輸入區對象
圖片對象 navigator 瀏覽器對象 反映了當前使用的瀏覽器的資料。
屬性
appCodeName 返回瀏覽器的“碼名”(?),流行的 IE 和 NN 都返回 'Mozilla'。
appName 返回瀏覽器名。IE 返回 'Microsoft Internet Explorer',NN 返回 'Netscape'。
appVersion 返回瀏覽器版本,包括了大版本號、小版本號、語言、操作平臺等信息。
platform 返回瀏覽器的操作平臺,對於 Windows 9x 上的瀏覽器,返回 'Win32'(大小寫可能有差異)。
userAgent 返回以上全部信息。例如,IE5.01 返回 'Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)'。
javaEnabled() 返回一個布爾值,代表當前瀏覽器允許不允許 Java。
screen 屏幕對象 反映了當前用戶的屏幕設置。
屬性
width 返回屏幕的寬度(像素數)。
height 返回屏幕的高度。
availWidth 返回屏幕的可用寬度(除去了一些不自動隱藏的類似任務欄的東西所占用的寬度)。
availHeight 返回屏幕的可用高度。
colorDepth 返回當前顏色設置所用的位數 - 1:黑白;8:256色;16:增強色;24/32:真彩色
window 窗口對象 最大的對象,它描述的是一個瀏覽器窗口。一般要引用它的屬性和方法時,不需要用“window.xxx”這種形式,而直接使用“xxx”。一個框架頁面也是一個窗口。
屬性
name 窗口的名稱,由打開它的連接()或框架頁()或某一個窗口調用的 open() 方法(見下)決定。一般我們不會用這個屬性。
status 指窗口下方的“狀態欄”所顯示的內容。通過對 status 賦值,可以改變狀態欄的顯示。
opener 用法:window.opener;返回打開本窗口的窗口對象。注意:返回的是一個窗口對象。如果窗口不是由其他窗口打開的,在 Netscape 中這個屬性返回 null;在 IE 中返回“未定義”(undefined)。undefined 在一定程度上等於 null。注意:undefined 不是 JavaScript 常數,如果你企圖使用“undefined”,那就真的返回“未定義”了。
self 指窗口本身,它返回的對象跟 window 對象是一模一樣的。最常用的是“self.close()”,放在標記中:“關閉窗口”。
parent 返回窗口所屬的框架頁對象。
top 返回占據整個瀏覽器窗口的最頂端的框架頁對象。
history 曆史對象,見下。
location 地址對象,見下。
document 文檔對象,見下。
方法
open() 打開一個窗口。用法:open(
<窗口名稱字符串>:描述被打開的窗口的名稱(window.name),可以使用'_top'、'_blank'等內建名稱。這裏的名稱跟“”裏的“target”屬性是一樣的。
<參數字符串>:描述被打開的窗口的樣貌。如果只需要打開一個普通窗口,該字符串留空(''),如果要指定樣貌,就在字符串裏寫上一到多個參數,參數之間用逗號隔開。
例:打開一個 400 x 100 的幹淨的窗口:
open('','_blank','width=400,height=100,menubar=no,toolbar=no,
location=no,directories=no,status=no,scrollbars=yes,resizable=yes')
參數
top=# 窗口頂部離開屏幕頂部的像素數
left=# 窗口左端離開屏幕左端的像素數
width=# 窗口的寬度
height=# 窗口的高度
menubar=... 窗口有沒有菜單,取值yes或no
toolbar=... 窗口有沒有工具條,取值yes或no
location=... 窗口有沒有地址欄,取值yes或no
directories=... 窗口有沒有連接區,取值yes或no
scrollbars=... 窗口有沒有滾動條,取值yes或no
status=... 窗口有沒有狀態欄,取值yes或no
resizable=... 窗口給不給調整大小,取值yes或no
open() 方法有返回值,返回的就是它打開的窗口對象。所以,
var newWindow = open('','_blank');
這樣把一個新窗口賦值到“newWindow”變量中,以後通過“newWindow”變量就可以控制窗口了。
close() 關閉一個已打開的窗口。
用法:window.close() 或 self.close():關閉本窗口;
<窗口對象>.close():關閉指定的窗口。
如果該窗口有狀態欄,調用該方法後瀏覽器會警告:“網頁正在試圖關閉窗口,是否關閉?”然後等待用戶選擇是否;如果沒有狀態欄,調用該方法將直接關閉窗口。
blur() 使焦點從窗口移走,窗口變為“非活動窗口”。
focus() 是窗口獲得焦點,變為“活動窗口”。不過在 Windows 98,該方法只能使窗口的標題欄和任務欄上的相應按鈕閃爍,提示用戶該窗口正在試圖獲得焦點。
scrollTo() 用法:[<窗口對象>.]scrollTo(x, y);使窗口滾動,使文檔從左上角數起的(x, y)點滾動到窗口的左上角。
scrollBy() 用法:[<窗口對象>.]scrollBy(deltaX, deltaY);使窗口向右滾動 deltaX 像素,向下滾動 deltaY 像素。如果取負值,則向相反的方向滾動。
resizeTo() 用法:[<窗口對象>.]resizeTo(width, height);使窗口調整大小到寬 width 像素,高 height 像素。
resizeBy() 用法:[<窗口對象>.]resizeBy(deltaWidth, deltaHeight);使窗口調整大小,寬增大 deltaWidth 像素,高增大 deltaHeight 像素。如果取負值,則減少。
alert() 用法:alert(<字符串>);彈出一個只包含“確定”按鈕的對話框,顯示<字符串>的內容,整個文檔的讀取、Script 的運行都會暫停,直到用戶按下“確定”。
confirm() 用法:confirm(<字符串>);彈出一個包含“確定”和“取消”按鈕的對話框,顯示<字符串>的內容,要求用戶做出選擇,整個文檔的讀取、Script 的運行都會暫停。如果用戶按下“確定”,則返回 true 值,如果按下“取消”,則返回 false 值。
prompt() 用法:prompt(<字符串>[, <初始值>]);彈出一個包含“確認”“取消”和一個文本框的對話框,顯示<字符串>的內容,要求用戶在文本框輸入一些數據,整個文檔的讀取、Script 的運行都會暫停。如果用戶按下“確認”,則返回文本框裏已有的內容,如果用戶按下“取消”,則返回 null 值。如果指定<初始值>,則文本框裏會有默認值。
事件
onload; onunload; onresize; onblur; onfocus; onerror
history 曆史對象 曆史對象指瀏覽器的瀏覽曆史。鑒於安全性的需要,該對象收到很多限制,現在只剩下下列屬性和方法。
屬性
length 曆史的項數。JavaScript 所能管到的曆史被限制在用瀏覽器的“前進”“後退”鍵可以去到的範圍。本屬性返回的是“前進”和“後退”兩個按鍵之下包含的地址數的和。
方法
back() 後退,跟按下“後退”鍵是等效的。
forward() 前進,跟按下“前進”鍵是等效的。
go() 用法:history.go(x);在曆史的範圍內去到指定的一個地址。如果 x < 0,則後退 x 個地址,如果 x > 0,則前進 x 個地址,如果 x == 0,則刷新現在打開的網頁。history.go(0) 跟 location.reload() 是等效的。
location 地址對象 它描述的是某一個窗口對象所打開的地址。要表示當前窗口的地址,只需要使用“location”就行了;若要表示某一個窗口的地址,就使用“<窗口對象>.location”。
注意 屬於不同協議或不同主機的兩個地址之間不能互相引用對方的 location 對象,這是出於安全性的需要。例如,當前窗口打開的是“www.a.com”下面的某一頁,另外一個窗口(對象名為:bWindow)打開的是“www.b.com”的網頁。如果在當前窗口使用“bWindow.location”,就會出錯:“沒有權限”。這個錯誤是不能用錯誤處理程序(Event Handler,參閱 onerror 事件)來接收處理的。
屬性
protocol 返回地址的協議,取值為 'http:','https:','file:' 等等。
hostname 返回地址的主機名,例如,一個“http://www.microsoft.com/china/”的地址,location.hostname == 'www.microsoft.com'。
port 返回地址的端口號,一般 http 的端口號是 '80'。
host 返回主機名和端口號,如:'www.a.com:8080'。
pathname 返回路徑名,如“http://www.a.com/b/c.html”,location.pathname == 'b/c.html'。
hash 返回“#”以及以後的內容,如“http://www.a.com/b/c.html#chapter4”,location.hash == '#chapter4';如果地址裏沒有“#”,則返回空字符串。
search 返回“?”以及以後的內容,如“http://www.a.com/b/c.asp?selection=3&jumpto=4”,location.search == '?selection=3&jumpto=4';如果地址裏沒有“?”,則返回空字符串。
href 返回以上全部內容,也就是說,返回整個地址。在瀏覽器的地址欄上怎麼顯示它就怎麼返回。如果想一個窗口對象打開某地址,可以使用“location.href = '...'”,也可以直接用“location = '...'”來達到此目的。
方法
reload() 相當於按瀏覽器上的“刷新”(IE)或“Reload”(Netscape)鍵。
replace() 打開一個 URL,並取代曆史對象中當前位置的地址。用這個方法打開一個 URL 後,按下瀏覽器的“後退”鍵將不能返回到剛才的頁面。
frames[]; Frame 框架對象 請參閱“使用框架和 Cookies”一章。
document 文檔對象 描述當前窗口或指定窗口對象的文檔。它包含了文檔從到的內容。
用法:document (當前窗口)
或 <窗口對象>.document (指定窗口)
屬性
cookie 關於 cookie 請參看“使用框架和 Cookies”一章。
lastModified 當前文檔的最後修改日期,是一個 Date 對象。
referrer 如果當前文檔是通過點擊連接打開的,則 referrer 返回原來的 URL。
title 指標記裏用
fgColor 指標記的 text 屬性所表示的文本顏色。
bgColor 指標記的 bgcolor 屬性所表示的背景顏色。
linkColor 指標記的 link 屬性所表示的連接顏色。
alinkColor 指標記的 alink 屬性所表示的活動連接顏色。
vlinkColor 指標記的 vlink 屬性所表示的已訪問連接顏色。
方法
open() 打開文檔以便 JavaScript 能向文檔的當前位置(指插入 JavaScript 的位置)寫入數據。通常不需要用這個方法,在需要的時候 JavaScript 自動調用。
write(); writeln() 向文檔寫入數據,所寫入的會當成標准文檔 HTML 來處理。writeln() 與 write() 的不同點在於,writeln() 在寫入數據以後會加一個換行。這個換行只是在 HTML 中換行,具體情況能不能夠是顯示出來的文字換行,要看插入 JavaScript 的位置而定。如在標記中插入,這個換行也會體現在文檔中。
clear() 清空當前文檔。
close() 關閉文檔,停止寫入數據。如果用了 write[ln]() 或 clear() 方法,就一定要用 close() 方法來保證所做的更改能夠顯示出來。如果文檔還沒有完全讀取,也就是說,JavaScript 是插在文檔中的,那就不必使用該方法。
現在我們已經擁有足夠的知識來做以下這個很多網站都有的彈出式更新通知了。
當然也可以先寫好一個 HTML 文件,在 open() 方法中直接 load 這個文件。
anchors[]; links[]; Link 連接對象
用法:document.anchors[[x]]; document.links[[x]];
document.anchors 是一個數組,包含了文檔中所有錨標記(包含 name 屬性的標記),按照在文檔中的次序,從 0 開始給每個錨標記定義了一個下標。
document.links 也是一個數組,包含了文檔中所有連接標記(包含 href 屬性的標記和
事件處理
事件處理概述
事件處理是對象化編程的一個很重要的環節,沒有了事件處理,程序就會變得很死,缺乏靈活性。事件處理的過程可以這樣表示:發生事件 - 啟動事件處理程序 - 事件處理程序作出反應。其中,要使事件處理程序能夠啟動,必須先告訴對象,如果發生了什麼事情,要啟動什麼處理程序,否則這個流程就不能進行下去。事件的處理程序可以是任意 JavaScript 語句,但是我們一般用特定的自定義函數(function)來處理事情。
指定事件處理程序
指定事件處理程序有三種方法:
方法一 直接在 HTML 標記中指定。這種方法是用得最普遍的。方法是:
<標記 ... ... 事件="事件處理程序" [事件="事件處理程序" ...]>
讓我們來看看例子:
這樣的定義標記,能使文檔讀取完畢的時候彈出一個對話框,寫著“網頁讀取完成,請慢慢欣賞”;在用戶退出文檔(或者關閉窗口,或者到另一個頁面去)的時候彈出“再見”。
方法二 編寫特定對象特定事件的 JavaScript。這種方法用得比較少,但是在某些場合還是很好用的。方法是:
...
(事件處理程序代碼)
...
例:
alert('網頁讀取完成,請慢慢欣賞!');
方法三 在 JavaScript 中說明。方法:
<事件主角 - 對象>.<事件> = <事件處理程序>;
用這種方法要注意的是,“事件處理程序”是真正的代碼,而不是字符串形式的代碼。如果事件處理程序是一個自定義函數,如無使用參數的需要,就不要加“()”。例:
...
function ignoreError() {
return true;
}
...
window.onerror = ignoreError; // 沒有使用“()”
這個例子將 ignoreError() 函數定義為 window 對象的 onerror 事件的處理程序。它的效果是忽略該 window 對象下任何錯誤(由引用不允許訪問的 location 對象產生的“沒有權限”錯誤是不能忽略的)。
事件詳解
onblur 事件 發生在窗口失去焦點的時候。
應用於:window 對象
onchange 事件 發生在文本輸入區的內容被更改,然後焦點從文本輸入區移走之後。捕捉此事件主要用於實時檢測輸入的有效性,或者立刻改變文檔內容。
應用於:Password 對象;Select 對象;Text 對象;Textarea 對象
onclick 事件 發生在對象被單擊的時候。單擊是指鼠標停留在對象上,按下鼠標鍵,沒有移動鼠標而放開鼠標鍵這一個完整的過程。
一個普通按鈕對象(Button)通常會有 onclick 事件處理程序,因為這種對象根本不能從用戶那裏得到任何信息,沒有 onclick 事件處理程序就等於廢柴。按鈕上添加 onclick 事件處理程序,可以模擬“另一個提交按鈕”,方法是:在事件處理程序中更改表單的 action, target, encoding, method 等一個或幾個屬性,然後調用表單的 submit() 方法。
在 Link 對象的 onclick 事件處理程序中返回 false 值(return false),能阻止瀏覽器打開此連接。即,如果有一個這樣的連接:Go!,那麼無論用戶怎樣點擊,都不會去到 www.a.com 網站,除非用戶禁止瀏覽器運行 JavaScript。
應用於:Button 對象;Checkbox 對象;Image 對象;Link 對象;Radio 對象;Reset 對象;Submit 對象
onerror 事件 發生在錯誤發生的時候。它的事件處理程序通常就叫做“錯誤處理程序”(Error Handler),用來處理錯誤。上邊已經介紹過,要忽略一切錯誤,就使用:
function ignoreError() {
return true;
}
window.onerror = ignoreError;
應用於:window 對象
onfocus 事件 發生在窗口得到焦點的時候。
應用於:window 對象
onload 事件 發生在文檔全部下載完畢的時候。全部下載完畢意味著不但 HTML 文件,而且包含的圖片,插件,控件,小程序等全部內容都下載完畢。本事件是 window 的事件,但是在 HTML 中指定事件處理程序的時候,我們是把它寫在標記中的。
應用於:window 對象
onmousedown 事件 發生在用戶把鼠標放在對象上按下鼠標鍵的時候。參考 onmouseup 事件。
應用於:Button 對象;Link 對象
onmouseout 事件 發生在鼠標離開對象的時候。參考 onmouseover 事件。
應用於:Link 對象
onmouseover 事件 發生在鼠標進入對象範圍的時候。這個事件和 onmouseout 事件,再加上圖片的預讀,就可以做到當鼠標移到圖像連接上,圖像更改的效果了。有時我們看到,在指向一個連接時,狀態欄上不顯示地址,而顯示其它的資料,看起來這些資料是可以隨時更改的。它們是這樣做出來的:
οnmοuseοver="window.status='Click Me Please!'; return true;"
οnmοuseοut="window.status=''; return true;">
應用於:Link 對象
onmouseup 事件 發生在用戶把鼠標放在對象上鼠標鍵被按下的情況下,放開鼠標鍵的時候。如果按下鼠標鍵的時候,鼠標並不在放開鼠標的對象上,則本事件不會發生。
應用於:Button 對象;Link 對象
onreset 事件 發生在表單的“重置”按鈕被單擊(按下並放開)的時候。通過在事件處理程序中返回 false 值(return false)可以阻止表單重置。
應用於:Form 對象
onresize 事件 發生在窗口被調整大小的時候。
應用於:window 對象
onsubmit 事件 發生在表單的“提交”按鈕被單擊(按下並放開)的時候。可以使用該事件來驗證表單的有效性。通過在事件處理程序中返回 false 值(return false)可以阻止表單提交。
應用於:Form 對象
onunload 事件 發生在用戶退出文檔(或者關閉窗口,或者到另一個頁面去)的時候。與 onload 一樣,要寫在 HTML 中就寫到標記裏。
有的 Web Masters 用這個方法來彈出“調查表單”,以“強迫”來者填寫;有的就彈出廣告窗口,唆使來者點擊連接。我覺得這種“οnunlοad="open..."”的方法很不好,有時甚至會因為彈出太多窗口而導致資源缺乏。有什麼對來者說就應該在網頁上說完,不對嗎?
應用於:window 對象
關於對象化編程的語句
現在我們有實力學習以下關於對象化編程,但其實屬於上一章的內容了。
with 語句 為一個或一組語句指定默認對象。
用法:with (<對象>) <語句>;
with 語句通常用來縮短特定情形下必須寫的代碼量。在下面的例子中,請注意 Math 的重複使用:
x = Math.cos(3 * Math.PI) + Math.sin(Math.LN10);
y = Math.tan(14 * Math.E);
當使用 with 語句時,代碼變得更短且更易讀:
with (Math) {
x = cos(3 * PI) + sin(LN10);
y = tan(14 * E);
}
this 對象 返回“當前”對象。在不同的地方,this 代表不同的對象。如果在 JavaScript 的“主程序”中(不在任何 function 中,不在任何事件處理程序中)使用 this,它就代表 window 對象;如果在 with 語句塊中使用 this,它就代表 with 所指定的對象;如果在事件處理程序中使用 this,它就代表發生事件的對象。
一個常用的 this 用法:
...
function check(formObj) {
...
}
...
...
...
...
...
這個用法常用於立刻檢測表單輸入的有效性。
自定義構造函數 我們已經知道,Array(),Image()等構造函數能讓我們構造一個變量。其實我們自己也可以寫自己的構造函數。自定義構造函數也是用 function。在 function 裏邊用 this 來定義屬性。
function <構造函數名> [(<參數>)] {
...
this.<屬性名> = <初始值>;
...
}
然後,用 new 構造函數關鍵字來構造變量:
var <變量名> = new <構造函數名>[(<參數>)];
構造變量以後,<變量名>成為一個對象,它有它自己的屬性——用 this 在 function 裏設定的屬性。
以下是一個從網上找到的搜集瀏覽器詳細資料的自定義構造函數的例子:
function Is() {
var agent = navigator.userAgent.toLowerCase();
this.major = parseInt(navigator.appVersion); //主版本號
this.minor = parseFloat(navigator.appVersion);//全版本號
this.ns = ((agent.indexOf('mozilla')!=-1) &&
((agent.indexOf('spoofer')==-1) && //是否 Netscape
(agent.indexOf('compatible') == -1)));
this.ns2 = (this.ns && (this.major == 3)); //是否 Netscape 2
this.ns3 = (this.ns && (this.major == 3)); //是否 Netscape 3
this.ns4b = (this.ns && (this.minor < 4.04)); //是否 Netscape 4 低版本
this.ns4 = (this.ns && (this.major >= 4)); //是否 Netscape 4 高版本
this.ie = (agent.indexOf("msie") != -1); //是否 IE
this.ie3 = (this.ie && (this.major == 2)); //是否 IE 3
this.ie4 = (this.ie && (this.major >= 4)); //是否 IE 4
this.op3 = (agent.indexOf("opera") != -1); //是否 Opera 3
this.win = (agent.indexOf("win")!=-1); //是否 Windows 版本
this.mac = (agent.indexOf("mac")!=-1); //是否 Macintosh 版本
this.unix = (agent.indexOf("x11")!=-1); //是否 Unix 版本
}
var is = new Is();
這個構造函數非常完整的搜集了瀏覽器的信息。我們看到它為對象定義了很多個屬性:major, minor, ns, ie, win, mac 等等。它們的意思見上面的注釋。把 is 變量定義為 Is() 對象後,用 if (is.ns) 這種格式就可以很方便的知道瀏覽器的信息了。我們也可以從這個構造函數中看到,它也可以使用一般的 JavaScript 語句(上例中為 var 語句)。
讓我們再來看一個使用參數的構造函數:
function myFriend(theName, gender, theAge, birthOn, theJob) {
this.name = theName;
this.isMale = (gender.toLowerCase == 'male');
this.age = theAge;
this.birthday = new Date(birthOn);
this.job = theJob
}
var Stephen = new myFriend('Stephen', 'Male', 18, 'Dec 22, 1982', 'Student');
從這個構造函數我們不但看到了參數的用法,還看到了不同的屬性用不同的數據型是可以的(上例五個屬性分別為:字符串,布爾值,數字,日期,字符串),還看到了構造函數裏也可以用構造函數來“構造”屬性。如果用了足夠的“保護措施”來避免無限循環,更可以用構造函數自身來構造自己的屬性。
使用框架和Cookies
使用框架
在講述 window 對象的時候,我們提到過,一個框架內的網頁也是 window 對象,也就是說,Frame 對象也是 window 對象。用最容易理解的話說,每一個 HTML 文件占用一個 window 對象,包括定義框架的網頁(“框架網頁”)。在 IE 裏用“
window.frames[x]
window.frames['frameName']
window.frameName
其中,x 指的是該 window 對象中指定的第幾個框架,與其它數組一樣,x 也是從零開始的。frameName 指的是該框架的名字,跟裏的“name”屬性一樣。
如果使用 window.frameName 指定的 window 對象又是一個框架網頁,那麼引用它的框架的方法:window.frameName.subFrameName。以此類推。
要注意的時,無論在何處,引用“window”對象所返回的,都是“當前”window 對象。如果要訪問其它 window 對象,就要用到 parent 和 top 屬性。parent 指的是“父級”window 對象,也就是包含當前 window 對象的框架網頁;top 指的是窗口最頂端的 window 對象。
使用框架還要密切留意你的 JavaScript 中定義的全局變量和自定義函數。它們都有它們的所屬——所在的 window 對象。要引用其它框架中的全局變量或自定義函數,都要用“窗口對象.框架對象[.框架對象…].全局變量或自定義函數”這種很煩的方法。
以上這個問題在建立連接時經常會被忽略:如果在中定義了一個默認目標窗口(
使用 Cookies
我們已經知道,在 document 對象中有一個 cookie 屬性。但是 Cookie 又是什麼?“某些 Web 站點在您的硬盤上用很小的文本文件存儲了一些信息,這些文件就稱為 Cookie。”—— MSIE 幫助。一般來說,Cookies 是 CGI 或類似,比 HTML 高級的文件、程序等創建的,但是 JavaScript 也提供了對 Cookies 的很全面的訪問權利。
在繼續之前,我們先要學一學 Cookie 的基本知識。
每個 Cookie 都是這樣的:
每個 Cookie 都有失效日期,一旦電腦的時鐘過了失效日期,這個 Cookie 就會被刪掉。我們不能直接刪掉一個 Cookie,但是可以用設定失效日期早於現在時刻的方法來間接刪掉它。
每個網頁,或者說每個站點,都有它自己的 Cookies,這些 Cookies 只能由這個站點下的網頁來訪問,來自其他站點或同一站點下未經授權的區域的網頁,是不能訪問的。每一“組”Cookies 有規定的總大小(大約 2KB 每“組”),一超過最大總大小,則最早失效的 Cookie 先被刪除,來讓新的 Cookie“安家”。
現在我們來學習使用 document.cookie 屬性。
如果直接使用 document.cookie 屬性,或者說,用某種方法,例如給變量賦值,來獲得 document.cookie 的值,我們就可以知道在現在的文檔中有多少個 Cookies,每個 Cookies 的名字,和它的值。例如,在某文檔中添加“document.write(document.cookie)”,結果顯示:
name=kevin; email=kevin@kevin.com; lastvisited=index.html
這意味著,文檔包含 3 個 Cookies:name, email 和 lastvisited,它們的值分別是 kevin, kevin@kevin.com 和 index.html。可以看到,兩個 Cookies 之間是用分號和空格隔開的,於是我們可以用 cookieString.split('; ') 方法得到每個 Cookie 分開的一個數組(先用 var cookieString = document.cookie)。
設定一個 Cookie 的方法是對 document.cookie 賦值。與其它情況下的賦值不同,向 document.cookie 賦值不會刪除掉原有的 Cookies,而只會增添 Cookies 或更改原有 Cookie。賦值的格式:
document.cookie = 'cookieName=' + escape('cookieValue')
+ ';expires=' + expirationDateObj.toGMTString();
是不是看到頭暈了呢?以上不是粗體字的地方是要照抄不誤的,粗體字是要按實際情況做出改動的。cookieName 表示 Cookie 的名稱,cookieValue 表示 Cookie 的值,expirationDateObj 表示儲存著失效日期的日期對象名,如果不需要指定失效日期,則不需要第二行。不指定失效日期,則瀏覽器默認是在關閉瀏覽器(也就是關閉所有窗口)之後過期。
看到了上面的一些下劃線了麼?這些是應該注意的地方。
首先 escape() 方法:為什麼一定要用?因為 Cookie 的值的要求是“只能用可以用在 URL 編碼中的字符”。我們知道“escape()”方法是把字符串按 URL 編碼方法來編碼的,那我們只需要用一個“escape()”方法來處理輸出到 Cookie 的值,用“unescape()”來處理從 Cookie 接收過來的值就萬無一失了。而且這兩個方法的最常用途就是處理 Cookies。其實設定一個 Cookie 只是“document.cookie = 'cookieName=cookieValue'”這麼簡單,但是為了避免在 cookieValue 中出現 URL 裏不准出現的字符,還是用一個 escape() 好。
然後“expires”前面的分號:注意到就行了。是分號而不是其他。
最後 toGMTString() 方法:設定 Cookie 的時效日期都是用 GMT 格式的時間的,其它格式的時間是沒有作用的。
現在我們來實戰一下。設定一個“name=rose”的 Cookie,在 3 個月後過期。
var expires = new Date();
expires.setTime(expires.getTime() + 3 * 30 * 24 * 60 * 60 * 1000);
/* 三個月 x 一個月當作 30 天 x 一天 24 小時
x 一小時 60 分 x 一分 60 秒 x 一秒 1000 毫秒 */
document.cookie = 'name=rose;expires=' + expires.toGMTString();
為什麼沒有用 escape() 方法?這是因為我們知道 rose 是一個合法的 URL 編碼字符串,也就是說,'rose' == escape('rose')。一般來說,如果設定 Cookie 時不用 escape(),那獲取 Cookie 時也不用 unescape()。
再來一次:編寫一個函數,作用是查找指定 Cookie 的值。
function getCookie(cookieName) {
var cookieString = document.cookie;
var start = cookieString.indexOf(cookieName + '=');
// 加上等號的原因是避免在某些 Cookie 的值裏有
// 與 cookieName 一樣的字符串。
if (start == -1) // 找不到
return null;
start += cookieName.length + 1;
var end = cookieString.indexOf(';', start);
if (end == -1) return unescape(cookieString.substring(start));
return unescape(cookieString.substring(start, end));
}
這個函數用到了字符串對象的一些方法,如果你不記得了(你是不是這般沒記性啊),請快去查查。這個函數所有的 if 語句都沒有帶上 else,這是因為如果條件成立,程序運行的都是 return 語句,在函數裏碰上 return,就會終止運行,所以不加 else 也沒問題。該函數在找到 Cookie 時,就會返回 Cookie 的值,否則返回“null”。
現在我們要刪除剛才設定的 name=rose Cookie。
var expires = new Date();
expires.setTime(expires.getTime() - 1);
document.cookie = 'name=rose;expires=' + expires.toGMTString();
可以看到,只需要把失效日期改成比現在日期早一點(這裏是早 1 毫秒),再用同樣的方法設定 Cookie,就可以刪掉 Cookie 了
---------------------------------------------以前