JScript基礎
# JScript基礎
注意
JScript的功能,正處於開發階段, 未正式推出前, 無保固服務, 不可用於實務工作中, 敬請斟酌使用。
# 1. 什麼是 JScript?
JScript 是 ECMA 262 語言規範(ECMAScript 編輯器 3)的一種實現。除了少數例外(爲了保持向後相容),JScript 完全實現了 ECMA 標準。本概述的目的就是引導您學習使用 JScript。
# 1.1. 使用 JScript
JScript 是一種解釋型的、基於對象的程式語言。儘管與 C++ 這樣成熟的物件導向的語言相比,JScript 的功能要弱一些,但對於它的預期用途而言,JScript 的功能已經足夠大了。
JScript 不是其他語言的精簡版(例如,它只是與 Java 有點模糊而間接的關係),也不是任何事物的簡化。不過,它有其侷限性。例如,您不能脫離產品的開發環境,使用該語言來編寫獨立運行的應用程式。
JScript 是一種寬鬆型別的語言。寬鬆型別意味著您不必顯式定義變數的數據型別。事實上 JScript 更進一步。您無法在JScriot上明確地定義數據型別。此外,在大多數情況下,JScript 將根據需要自動進行轉換。例如,如果將一個數值新增到由文字組成的某項(一個字串),該數值將被轉換為文字。
本使用者指南的其餘部分是 JScript 特性概述。
注意
下面大多數示例的程式碼比實際 Web 頁中的程式碼應該更明確,並且不是太複雜。其目的是闡明相關概念,而不是提供最優的簡短編碼和風格。在任何情況下,如果六個月以後還能毫不費力地閱讀和理解所編寫的程式碼,則說明這些程式碼寫得不錯。
# 2. 編寫 JScript 程式碼
與其他許多程式語言一樣, JScript 是用文字方式編寫的,並被組織成為語句、由相關的語句集組成的塊、以及註釋。在一條語句內可以使用變數、比如字串和數字(稱為「文字」)的立即數、以及表達式。
# 2.1. 語句
JScript 程式是語句的集合。一條 JScript 語句相當於英語中的一個完整句。JScript 語句將表達式組合起來,完成一個任務。
一條語句由一個或多個表達式、關鍵字或者運算子(符號)組成。通常一條語句會寫作一行,但是一條語句可以超過兩行或更多行。兩條或更多條語句也可以寫在同一行上,語句之間用分號「;」隔開。通常,每一新行開始一條新語句。不過顯式地終止語句是一個好方法。這是用分號 (;)來實現的,分號是 JScript 語句的終止字元。下面給出 JScript 語句的兩隔示例。
aBird = "Robin"; //將文字「Robin」賦值給變數 aBird
var today = now; // 將今天的日期賦值給變數 today
2
用大括號({})括起來的一組 JScript 語句稱為一個語句塊。分組到一個語句塊中的語句通常可當作單條語句處理。這就是說在 JScript 期望有一條單個語句的大多數地方可以使用語句塊。應該注意以 for 和 while 打頭的循環語句是例外情況。注意,語句塊中的原始語句以分號結束,但語句塊本身並不以分號結束。
通常,在函式和條件語句中使用語句塊。注意,JScript 與 C++ 以及其他某些語言不同,它不認為語句塊是一個新的範圍;只有函式建立新範圍。在下面的示例中,第一條語句開始定義一個函式,該函式包含一個五條語句組成的語句塊。語句塊后的三條語句沒有用大括號括起來;這些語句不是一個語句塊,所以就不是函式定義的一部分。
function convert(inches) {
feet = inches / 12; // 這五條語句屬於一個語句塊。
miles = feet / 5280;
nauticalMiles = feet / 6080;
cm = inches * 2.54;
meters = inches / 39.37;
}
km = meters / 1000; // 這三條語句不在語句塊內。
kradius = km;
mradius = miles;
2
3
4
5
6
7
8
9
10
# 2.2. 註釋
單行的 JScript 註釋以一對正斜槓(//)開始。下面給出一個單行註釋的示例。
aGoodIdea = "Comment your code thoroughly."; // 這是一個單行註釋。
多行註釋以一個正斜槓加一個星號的組合()結束。
注意
如果您試圖將一個多行註釋插入到另一個中,JScript 不能按正常的方式解釋產生的多行註釋。標明嵌入的多行註釋結束的 */ 被認為是整個多行註釋的結尾。這就意味著嵌入多行註釋之後的文字不再被認為是註釋;相應地,它將被解釋為 JScript 程式碼,並會產生語法錯誤。
建議將所有的註釋寫為單行註釋的語句塊。這樣您以後就能夠將大段的程式碼與多行註釋區分開。
//這是另一種多行註釋,寫成一系列單行註釋。
// 在執行完該語句后,可以使用 aGoodIdea 變數的名字來引用其內容,
// 如下一條語句那樣,即採用連線操作將字串文字新增到
// aGoodIdea 變數,以建立一個新的變數。
var extendedIdea = aGoodIdea + " You never know when you'll have to figure out what it does.";
2
3
4
5
6
7
# 2.3. 賦值和相等
JScript 語句中使用等號 (=)給變數賦值:等號是賦值運算子。= 運算子左邊的操作項總是一個 Lvalue。Lvalue 可以是:
- 變數,
- 陣列元素,
- 對像屬性。
= 運算子右邊的操作項總是一個 Rvalue。Rvalues 可以是任何型別的一個任意值,包括表達式的值。下面給出一個 JScript 賦值語句的示例。
anInteger = 3;
JScript 編譯器解釋本語句的意義為:「將 3 賦給變數 anInteger」或「anInteger 的值為 3」。
確定您理解了 = 運算子(賦值)和 == 運算子(相等)的差異。在比較兩個值是否相等時,應使用兩個等於號 (==)。這些內容將在 控制程式的流程 中詳細介紹。
# 2.4. 表達式
JScript 表達式是指 JScript 直譯器能夠計算產生值的 JScript 「短語」。這個值可以是任何有效的 JScript 型別 — 數字、字串、對象,等等。最簡單的表達式是文字。下面給出 JScript 文字表達式的一些示例。
3.9 // 數字文字
"Hello!" // 字串文字
false // 布爾文字
null // 文字空值
{x:1, y:2} // 對像文字
[1,2,3] // 陣列文字
function(x){return x*x;} // 函式文字
2
3
4
5
6
7
更多複雜的表達式中包含變數、函式、函式呼叫以及其他表達式。可以用運算子將表達式組合,建立複合表達式。運算子可以是:
+ // 加法
- // 減法
* // 乘法
/ // 除法
2
3
4
下面給出 JScript 複合表達式的一些示例。
var anExpression = 3 * (4 / 5) + 6;
var aSecondExpression = Math.PI * radius * radius;
var aThirdExpression = aSecondExpression + "%" + anExpression;
var aFourthExpression = "(" + aSecondExpression + ") % (" + anExpression + ")";
2
3
4
# 3. JScript 的變數
任何程式語言中,用一塊數據量化一個概念。
How old am I?
在 JScript 中,變數是給概念的名稱;它代表了給出瞬間的值。當使用該變數時,實際是用的它所代表的數據。給出示例:
NumberOfDaysLeft = EndDate – TodaysDate;
機械的理解是使用變數來儲存、得到並操作程式中出現的所有的不同值。建立有意義的變數名稱;便於別人理解程式。
# 3.1. 變數聲明
變數在程式中的第一次出現是在聲明中。變數在第一次用到時就設定于記憶體中,便於後來在程式中引用。使用變數之前先進行聲明。可以使用 var 關鍵字來進行變數聲明。
var count; // 單個聲明。
var count, amount, level; // 用單個 var 關鍵字聲明的多個聲明。
var count = 0, amount = 100; // 一條語句中的變數聲明和初始化。
2
3
如果在 var 語句中沒有初始化變數,變數自動取 JScript 值 undefined。儘管並不安全,但聲明語句中忽略 var 關鍵字是合法的 JScript 語法。這時,JScript 直譯器給予變數全域性範圍的可見度。當在過程級中聲明一個變數時,它不能用於全域性範圍;這種情況下,變數聲明必須用 var 關鍵字。
# 3.2. 變數命名
變數名稱是一個識別符號。JScript 中,用識別符號來:
- 命名變數,
- 命名函式,
- 給出循環的標籤。
JScript的變數的名稱可以是任意長度。建立合法的變數名稱應遵循如下規則:
- 第一個字元必須是一個 ASCII 字母(大小寫均可),或一個下劃線(_)。注意第一個字元不能是數字。
- 後續的字元必須是字母、數字或下劃線。
- 變數名稱一定不能是 保留字。
下面給出合法變數名稱的一些示例:
_pagecount Part9 Number_Items
下面給出無效變數名稱的一些示例:
99Balloons // 不能以數字開頭。
Smith&Wesson // 「與」符號(&)字元用於變數名稱是無效的。
2
當要聲明一個變數並進行初始化,但又不想指定任何特殊值,可以賦值為 JScript 值 null。下面給出示例。
var bestAge = null; var muchTooOld = 3 * bestAge; // muchTooOld 的值為 0。
如果聲明了一個變數但沒有對其賦值,該變數存在,其值為JScript 值 undefined。下面給出示例。
var currentCount; var finalCount = 1 * currentCount; // finalCount 的值為 NaN,因為 currentCount 為 undefined。
注意在 JScript 中 null 和 undefined 的主要區別是 null 的操作象數字 0,而 undefined 的操作象特殊值NaN (不是一個數字)。對 null 值和 undefined 值作比較總是相等的。
JScript不支援使用未經過聲明的變數。
var volume = length * width; // 錯誤 — length 和 width 並不存在。
# 4. JScript 的數據型別
JScript 有三種主要數據型別、兩種複合數據型別和兩種特殊數據型別。
主要(基本)數據型別是:
- 字串
- 數值
- 布爾
複合(引用)數據型別是:
- 對像
- 陣列
特殊數據型別是:
- Null
- Undefined
表達式中操作項的數據型別相同時 JScript 直譯器才能對其求值。如果表達式試圖對兩個不同的數據型別(如一個為數字,另一個為字串)執行運算,將產生錯誤結果。
# 4.1. 字串數據型別
一個字串值是排在一起的一串零或零以上的 Unicode 字元(字母、數字和標點符號)。字串數據型別用來表示 JScript 中的文字。程式中可以包含字串文字,這些字串文字放在一對匹配的的單引號或雙引號中。字串中可以包含雙引號,該雙引號兩邊需加單引號,也可以包含單引號,該單引號兩邊需加雙引號。下面是字串的示例:
"Happy am I; from care I』m free!" '"Avast, ye lubbers!" roared the technician.' "42" 'c'
請注意,JScript 中沒有表示單個字元的型別(如 C++ 的 char)。要表示 JScript 中的單個字元,應建立一個只包含一個字元的字串。包含零個字元("")的字串是空(零長度)字串。
# 4.2. 數值數據型別
在 JScript 中JScript 數值可以是其中任意一種(JScript 內部將所有的數值表示為浮點值)。
# 4.2.1. 整型值
整型值可以是正整數,負整數和 0。可以用 10 進位制,8 進位制和 16 進位制來表示。在 JScript 中大多數字是用十進制表示的。加字首「0」表示 8 進位制的整型值,只能包含 0 到 7 的數字。字首為「0」同時包含數字「8」或「9」的數被解釋為十進制數。
加字首「0x」(零和x|X)表示 16 進位制整型值。可以包含數字 0 到 9,以及字母 A 到 F(大寫或小寫)。使用字母 A 到 F 表示十進制 10 到 15 的單個數字。就是說 0xF 與 15 相等,同時 0x10 等於 16。
八進制和十六進制數可以為負,但不能有小數位,同時不能以科學計數法(指數)表示。
# 4.2.2. 浮點值
浮點值為帶小數部分的數。也可以用科學計數法來表示。這就是說,大寫或小寫「e」用來表示 10 的次方。JScript用數值表示的八位元組 IEEE754 浮點標準。這意味著數字最大可以到±1.7976931348623157x10308,最小到±5x10-324。以「0」開始且包含小數點的數字被解釋為小數浮點數。
注意以「0x」或「00」開始幷包含小數點的數將發生錯誤。以下是 JScript 中數字的例子。
數字 | 描述 | 等價十進制數 |
---|---|---|
.0001, 0.0001, 1e-4, 1.0e-4 | 四個相等的浮點數。 | 0.0001 |
3.45e2 | 浮點數。 | 345 |
42 | 整數。 | 42 |
0378 | 整數。雖然看起來是八進制數(以0開頭),但是8不是有效的八進制數字,所以為十進制數。 | 378 |
0377 | 八進制整數。注意它雖然看起來比上面的數只小1,但實際數值有很大不同。 | 255 |
0.0001 | 浮點數。雖然以零開頭,但由於帶有小數點所以不是八進制數。 | 0.0001 |
00.0001 | 錯誤。兩個零開頭表示為八進制,但八進制數不能帶有小數部分。 | N/A (編譯錯誤) |
0Xff | 十六進制整數。 | 255 |
0x37CF | 十六進制整數。 | 14287 |
0x3e7 | 十六進制整數。注意『e』並不被認為指數。 | 999 |
0x3.45e2 | 錯誤。十六進制數不能有小數部分。 | N/A (編譯錯誤) |
另外,JScript包含特殊值數字。它們是:
- NaN (不是數)。當對不適當的數據進行數學運算時使用,例如字串或未定義值。
- 正無窮大。在JScript中如果一個正數太大的話使用它來表示。
- 負無窮大。在JScript中如果一個負數太大的話使用它來表示。
- 正0和負0。JScript區分正0和負0。
# 4.3. Boolean數據型別
儘管字串和數字型別可以有無數不同的值,boolean 數據型別卻只有兩個值。它們是文字 true 和 false。Boolean值是一個真值,它表示一個狀態的有效性(說明該狀態為真或假)。
程式中的比較通常得到一個 Boolean 結果。考慮下一行 JScript 程式碼。
y = (x == 2000);
這裡要比較變數 x 的值是否與數字 2000 相等。如果相等,比較的結果為 Boolean 值 true,並將其賦給變數 y。如果x與2000不等,則比較的結果為boolean值false。
Boolean值在結構控制中尤其有用。可以將直接建立 boolean 值的比較與用使用該 boolean 值的語句相組合。考慮下面的JScript程式碼範例。
if (x == 2000) z = z + 1; else x = x + 1;
當 boolean 值為 true 時,JScript 中的 if/else 語句執行一個操作(這樣,z = z + 1),而當 boolean 值為 false 時執行另一個操作(x = x + 1)。
可以使用任意表達式作比較表達式。任何值為0、null、未定義或空字串的表達式被解釋為 false。其他任意值的表達式解釋為 true。例如,可以使用如下表達式:
if (x = y + z) // 這可能不是想要的結果 – 如下!
注意上面的程式碼並不檢查 x 是否與 y+z 相等,因為僅使用了一個等號(賦值)。相反的,上面的程式碼將 y+z 賦給變數 x,然後檢查整個表達式的值是否為零。要檢查 x 是否與 y+z 相等,使用如下程式碼。
if (x == y + z) //
有關比較的詳細資訊,請參見控制程式的流程。
# 4.4. Null 數據型別
在 JScript 中數據型別 null 只有一個值:null。關鍵字 null 不能用作函式或變數的名稱。
包含 null 的變數包含「無值」或「無對象」。換句話說,該變數沒有儲存有效的數、字串、boolean、陣列或對象。可以通過給一個變數賦 null 值來清除變數的內容。
請注意,在 JScript 中,null 與 0 不相等(與在 C 和 C++ 中不同)。同時應該指出的是,JScript中 typeof 運算子將報告 null 值為 Object 型別,而非型別 null。這點潛在的混淆是爲了向下相容。
# 4.5. Undefined 數據型別
如下情況使返回 undefined 值:
- 對像屬性不存在,
- 聲明了變數但從未賦值。
注意不能通過與 undefined 做比較來測試一個變數是否存在,雖然可以檢查它的型別是否為「undefined」。在以下的程式碼範例中,假設程式設計師想測試是否已經聲明變數 x :
// 這種方法不起作用
if (x == undefined)
// 作某些操作
// 這個方法同樣不起作用- 必須檢查
// 字串 "undefined"
if (typeof(x) == undefined)
// 作某些操作
// 這個方法有效
if (typeof(x) == "undefined")
// 作某些操作
2
3
4
5
6
7
8
9
10
11
12
考慮將 undefined 值與null做比較。
someObject.prop == null;
如下情況時,比較的結果為 true,
- 如果屬性 someObject.prop 包含 null 值,
- 如果屬性 someObject.prop 不存在。
- 要檢查一個對像屬性是否存在,可以使用新的 in 運算子:
if ("prop" in someObject) // someObject 有屬性 'prop'
# 5. JScript 的運算子
JScript 具有全範圍的運算子,包括算術、邏輯、位、賦值以及其他某些運算子。
計算 | 邏輯 | 位運算 | 賦值 | 雜項 | |||||
---|---|---|---|---|---|---|---|---|---|
描述 | 符號 | 描述 | 符號 | 描述 | 符號 | 描述 | 符號 | 描述 | 符號 |
負值 | - | 邏輯非 | ! | 按位取反 | ~ | 賦值 | = | 刪除 | delete |
遞增 | ++ | 小於 | < | 按位左移 | << | 運算賦值 | oP= | typeof 運算子 | typeof |
遞減 | -- | 大於 | > | 按位右移 | >> | void | void | ||
乘法 | * | 小於等於 | <= | 無符號右移 | >>> | instanceof | instanceof | ||
除法 | / | 大於等於 | >= | 按位與 | & | new | new | ||
取模運算 | % | 等於 | == | 按位異或 | ^ | in | in | ||
加法 | + | 不等於 | != | 按位或 | |||||
減法 | - | 邏輯與 | && | ||||||
邏輯或 | |||||||||
條件(三元運算子) | ?: | ||||||||
逗號 | , | ||||||||
嚴格相等 | === | ||||||||
非嚴格相等 | !== |
== (相等)與 === (嚴格相等)的區別在於恒等運算子在比較前強制轉換不同型別的值。例如,恒等對字串 "1" 與數值 1 的比較結果將為 true。而嚴格相等不強制轉換不同型別的值,因此它認為字串 "1" 與數值 1 不相同。
基本的字串、數值和布林值是按值比較的。如果它們的值相同,比較結果為相等。對像(包括Array、Function、String、Number、Boolean、Error、Date以及 RegExp 對像)按引用比較。即使這些型別的兩個變數具有相同的值,只有在它們正好為同一對像時比較結果才為 true。
例如:
// 具有相同值的兩個基本字串。
var string1 = "Hello";
var string2 = "Hello";
// 具有相同值的兩個 String 對象。
var StringObject1 = new String(string1);
var StringObject2 = new String(string2);
// 比較結果為 true。
if (string1 == string2)
// 執行某些命令(將要運行的)。
// 比較結果為 false。
if (StringObject1 == StringObject2)
//執行某些命令(不會運行)。
// 要比較 String 對象的值,
// 用 toString() 或者 valueOf() 方法。
if (StringObject1.valueOf() == StringObject2)
//執行某些命令(將要運行的)。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 6. 控制程式的流程
JScript 程式中的語句一般是按照寫的順序來運行的。這種運行稱為順序運行,是程式流的預設方向。
與順序運行不同,另一種運行將程式流轉換到程式的另外的部分。也就是,不按順序運行下一條語句,而是運行另外的語句。
要使程式可用,該控制的轉換必須以邏輯方式執行。程序控制的轉換是基於一個「決定」,這個「決定」結果是真或假(返回 Boolean 型 true 或 false)。 建立一個表達式,然後測試其是否為真。主要有兩種程式結構實現本功能。
第一種是選擇結構。用來指明兩種程式流方向,在程式中建立一個交叉點(像岔路)。在 JScript 中有四種選擇結構可用。
- 單一選擇結構(if),
- 二路選擇結構(if/else),
- 內聯三元運算子 ?:
- 多路選擇結構(switch)。
第二種型別的程序控制結構是循環結構。使用循環結構來指明當某些條件保持為真時要重複的動作。當控制語句的條件得到滿足時(通常在某些迭代的特定數字后),控制跳過循環結構傳遞到下條語句。在 JScript 中有四種循環結構可用。
- 在循環的開頭測試表達式(while),
- 在循環的末尾測試表達式(do/while),
- 對對象的每個屬性都進行操作(for/in),
- 由計數器控制的循環(for)。
通過巢狀和堆疊選擇、循環控制結構,可以建立相當複雜的程式。
第三種形式的結構程式流由意外處理給出,本文件不作討論。
# 6.1. 使用條件語句
JScript 支援 if 和 if...else 條件語句。在 if 語句中將測試一個條件,如果該條件滿足測試,執行相關的 JScript 編碼。在 if...else 語句中,如果條件不滿足測試,則將執行不同的程式碼。最簡單的 if 語句格式可以在一行中寫完,不過更常見的是多行的 if 和 if...else 語句。
下述示例演示了使用 if 和 if...else 語句的各種可能的語法。第一個示例演示了最簡單的布爾測試。當(且僅當)括號之間的項的值為(或者可被強制轉換為) true 時,if 後續的語句或語句塊才會被執行。
// smash() 函式是在該程式碼的其他地方定義的。
// 布爾測試,看 newShip 是否為 true。
if (newShip)
smash(champagneBottle,bow);
// 在本示例中,除非兩個條件都為真,否則該測試將不會被滿足。
if (rind.color == "deep yellow " && rind.texture == "large and small wrinkles")
{
theResponse = ("Is it a Crenshaw melon?");
}
// 在本示例中,只要任何一個條件為真,則測試即會滿足。
var theReaction = "";
if ((dayOfWeek == "Saturday") || (dayOfWeek == "Sunday"))
{
theReaction = ("I'm off to the beach!");
}
else
{
theReaction = ("Hi ho, hi ho, it's off to work I go!");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 6.2. 條件運算子
JScript 也支援隱式的條件格式。該格式在要測試的條件后使用一個問號(而不是在條件前的 if )。它也指定兩個可選項,一個在滿足條件時使用,另一個在條件不滿足時使用。這兩個選擇項之間必須用一個冒號隔開。
var hours = ""; // 下面的程式碼指定 hours 是包含 theHour 的內容,
// 還是包含 theHour - 12 的內容。
hours += (theHour >= 12) ? " PM" : " AM";
2
3
4
如果要一起測試多個條件,並且知道某個條件比其他條件更可能滿足或不滿足測試,可以使用稱為「短路計算」的特性來加速程式的運行速度。當 JScript 計算邏輯表達式時,只計算要得到結果所需的子表達式。
例如,如果有一個「與」表達式,如 ((x == 123) && (y == 42)),JScript 首先檢查 x 是否為 123。如果不是,即使 y 等於 42,整個表達式的值也不可能為 true。因此,並不對 y 作測試,JScript 返回 false 值。
類似地,如果多個條件中只要有一個為真(使用 || 運算子),則當任何一個條件滿足該測試時測試則停止。如果要測試的條件包括函式呼叫或其他複合表達式,這種處理方式就有效。出於此種想法,寫 OR 表達式時,先寫最有可能為 true 的條件。寫 AND 表達式時,先寫最有可能為 false 的條件。
以這種方式設計程式的好處的一個示例是:在下例中如果 runfirst() 返回 0 或 false, 則不會運行 runsecond()。
if ((runfirst() == 0) || (runsecond() == 0)) { // 若干程式碼。
}
2
# 6.3. 使用循環
有多種方式來重複執行一條語句或語句塊。通常重複執行被稱為循環或重複。重複只是循環的一個運行。典型情況是用一個變數測試來進行控制,每執行一次循環變數的取值都會更改。JScript 支援四種循環: for 循環、 for...in 循環、 while 循環、 do...while 循環。
# 6.3.1. 使用 for 循環
for 語句指定了一個計數器變數,一個測試條件,以及更新該計數器的操作。在每次循環的重複之前,都將測試該條件。如果測試成功,將運行循環中的程式碼。如果測試不成功,不運循環中的程式碼,程式繼續運行緊跟在循環后的第一行程式碼。在執行該循環后,計算機變數將在下一次循環之前被更新。
如果循環條件永不會滿足,則不執行該循環。如果測試條件始終滿足,則將導致無限循環。在有些情況下,前者可能是合乎需要的,而後者幾乎沒有用處,因此在編寫循環條件時一定要注意。
var howFar = 10; // 將循環次數限制為 10。
var sum = new Array(howFar); // 建立一個稱為 sum 並具有 10 個成員的陣列,這 10 個成員從 0 到 9。
var theSum = 0;
sum[0] = 0;
for (var icount = 0; icount < howFar; icount++) { // 在本例中將從 0 到 9 進行計數。
theSum += icount;
sum[icount] = theSum;
}
var newSum = 0;
for (var icount = 0; icount > howFar; icount++) { // 該循環根本不會被執行,因為 icount 不大於 howFar。
newSum += icount;
}
var sum = 0;
for (var icount = 0; icount >= 0; icount++) { // 這是一個無限循環。
sum += icount;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 6.3.2. 使用 for...in 循環
JScript 提供了一種特別的循環方式來遍歷一個對象的所有使用者定義的屬性或者一個陣列的所有元素。for...in 循環中的循環計數器是一個字串,而不是數字。它包含目前屬性的名稱或者目前陣列元素的下標。
下面的程式碼範例應在 Internet 瀏覽器中運行,因為它使用 alert 方法,該方法不屬於 JScript。
// 建立具有某些屬性的對象
var myObject = new Object();
myObject.name = "James";
myObject.age = "22";
myObject.phone = "555 1234";
// 列舉(循環)對象的所有屬性
for (prop in myObject) {
// 顯示 "The property 'name' is James",等等。
window.alert("The property '" + prop + "' is " + myObject[prop]);
}
2
3
4
5
6
7
8
9
10
11
儘管 for...in 循環看起來像 VBScript 的 For Each...Next 循環,其實並不一樣。JScript 的 for...in 循環重複JScript 對像所有的屬性。VBScript 的 For Each...Next 循環重複集合中的所有專案。要循環 JScript 中的所有集合,需要用 Enumerator 對象。儘管某些對像(像 Internet 瀏覽器中的那些)支援 VBScript 的 For Each...Next 和 JScript 的 for...in 循環,但多數對象並不都支援。
# 6.3.3. 使用 while 循環
while 循環相似於 for 循環。其不同之處是 while 循環沒有內建的計數器或更新表達式。如果希望控制語句或語句塊的循環執行,需要不只是「運行該程式碼 n 次」,而是更復雜的規則,用 while 循環。下面的示例使用 Internet 瀏覽器對像模型和 while 循環來詢問使用者一個簡單的問題。
var x = 0;
while ((x != 42) && (x != null)) {
x = window.prompt("What is my favourite number?", x);
}
if (x == null) window.alert("You gave up!");
else window.alert("Yep - it's the Ultimate Answer!");
2
3
4
5
6
注意 由於 while 循環沒有顯式的內建計數器變數,因此比其他型別的循環更容易產生無限循環。此外,由於不易發現循環條件是在何時何地被更新的,很容易編寫一個實際上從不更新條件的 while 循環。因此在編寫 while 循環時應特別小心。
同上面所提到的,在 JScript 中還有 do...while 循環與 while 循環相似,不同處在於它總是至少運行一次,因為是在循環的末尾檢查條件,而不是在開頭。例如,上面的循環可以被改寫為:
var x = 0;
do {
x = window.prompt("What is my favourite number?", x);
} while ((x != 42) && (x != null));
if (x == null) window.alert("You gave up!");
else window.alert("Yep - it's the Ultimate Answer!");
2
3
4
5
6
# 6.3.4. 使用 break 和 continue 語句
在 JScript 中當某些條件得到滿足時,用 break 語句來中斷一個循環的運行。(請注意,也用 break 語句退出一個 switch 塊。)。如果是一個 for 或者 for...in 循環,在更新計數器變數時使用 continue 語句越過餘下的程式碼塊而直接跳到下一個循環中。
下面的例子基於前面的示例用 break 和 continue 語句控制循環。
var x = 0;
do {
x = window.prompt("What is my favourite number?", x); // 判斷使用者是否選擇取消?如果是,退出循環。
if (x == null)
break;
// 是否輸入一個數?
// 如果是則無需要求輸入一個數。
if (Number(x) == x)
continue;
// 要求使用者只輸入數字。
window.alert("Please only enter in numbers!");
} while (x != 42)
if (x == null)
window.alert("You gave up!");
else
window.alert("Yep - it's the Ultimate Answer!");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 7. JScript 函式
JScript 函式執行操作,也可以返回值。某些時候是計算或比較的結果。函式又被稱為「全域性方法」。
一個函式中包含有幾個操作。這樣可使得程式碼更合理化。可以寫一組語句並給其命名,然後通過呼叫它並傳遞其需要的資訊來運行整組語句。
給函式傳遞資訊可以把資訊放在函式名稱後面的圓括號中。傳遞給函式的資訊稱作參數。某些函式根本不帶任何參數,而其他函式帶一個或者多個參數。在某些函式中,參數的個數取決於如何使用該函式。
JScript 支援兩種函式:一類是語言內部的函式,另一類是自己建立的。
# 7.1. 特殊的內部函式
JScript 語言包含很多內部函式。其可使用的函式可參考各產品手冊中的系統函式、自定函式與系統副程式、自定副程式的說明。
# 7.2. 建立自己的函式
在必要的時候,可以建立並使用自己的函式。一個函式的定義中包含了一個函式語句和一個 JScript 語句塊。
下面示例中的 Checktriplet 函式以三角形的邊長為參數。通過檢視三條邊的長度是否可以組成一個畢達哥拉斯三元組(直角三角形斜邊長度的平方等於其他兩條邊長的平方和)來計算該三角形是否為直角三角形。實際測試時 checkTriplet 函式要呼叫另兩個函式中的一個函式。
注意在浮點數測試版本中極小數(「epsilon」)作為測試變數的使用。由於浮點運算的不確定性和舍入誤差,除非問題中的三個值均已知為整數,直接測試這三個數是否組成畢達哥拉斯三元組是不可行的。因為直接的測試更為準確,本示例中的程式碼確定其是否可行,如果可行則使用它。
var epsilon = 0.00000000001;
// 一些需要測試的極小數字。
// 測試整數的函式。
function integerCheck(a, b, c) {
// 測試。
if ((a * a) == ((b * b) + (c * c)))
return true;
return false;
} // 整數檢查函式的結尾。
// 測試浮點數的函式。
function floatCheck(a, b, c) {
// 得到測試數值。
var delta = ((a * a) - ((b * b) + (c * c)))
// 測試需要絕對值
delta = Math.abs(delta);
// 如果差小於 epsilon,那麼它相當接近。
if (delta < epsilon)
return true;
return false;
} // 浮點檢查函式的末尾。
// 三元檢查。
function checkTriplet(a, b, c) {
// 建立臨時變數,用於交換值
var d = 0;
// 先將最長的移動到位置「a」。
// 需要的話交換 a 和 b
if (b > a) {
d = a;
a = b;
b = d;
}
// 需要的話交換 a 和 c
if (c > a) {
d = a;
a = c;
c = d;
}
// 測試全部的 3 個值,看其是否為整數?
if (((a % 1) == 0) && ((b % 1) == 0) && ((c % 1) == 0)) {
// 如果成立,使用精確檢查。
return integerCheck(a, b, c);
} else {
// 如果不成立,取儘可能相近的。
return floatCheck(a, b, c);
}
} // 三元檢查函式的末尾。
// 下面的三個語句賦給範例值,用於測試。
var sideA = 5;
var sideB = 5;
var sideC = Math.sqrt(50.001);
// 呼叫函數。呼叫后,'result' 中包含了結果。
var result = checkTriplet(sideA, sideB, sideC);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 8. JScript對像
JScript 對象是屬性和方法的集合。一個方法就是一個函式,是對象的成員。屬性是一個值或一組值(以陣列或對象的形式),是對象的成員。JScript 支援四種類型的對象:內部對像、產生的對象、宿主給出的對象(如瀏覽器中的 window 和 document)以及 ActiveX 對像(外部元件)。
# 8.1. 作為陣列的對象
在 JScript 中,對像和陣列幾乎是以相同的方式處理的。對像和陣列均可以被賦予任意值,實際上陣列只是一種特殊的對象。陣列和對象的區別在於陣列有一個「奇妙的」 length 屬性,而對像沒有。這意味著可以給陣列的一個元素賦予比其他元素更大的值。例如,myArray[100] = "hello" — 然後 length 屬性將自動地被更新為 101(新長度)。同樣,如果修改陣列的 length 屬性,將刪除不再是陣列部分的元素。
JScript 中所有的對象均支援「expando」屬性或那些可以在運行時動態新增和刪除的屬性。這些屬性可以有包含數字的任意名稱。如果屬性的名稱是簡單的識別符號<<參考識別符號規則>>,可以在對像名稱的後面加句點,例如:
var myObj = new Object();
// 新增兩個 expando 屬性,'name' 和 'age'
myObj.name = "Fred";
myObj.age = 42;
2
3
4
如果屬性名稱不是一個簡單的識別符號,或者在寫程式的時候不知道,可以在方括號中使用任意表達式來索引屬性。在 JScript 中所有 expando 屬性的名稱在被新增到對像之前被轉換為字串。
var myObj = new Object();
// 新增兩個無法寫在 object.property 語
// 法中的 expando 屬性。
// 第一個屬性包含無效字元(空格),
// 所以必須寫在方括號里。
myObj["not a valid identifier"] = "This is the property value";
// 第二個 expando 名稱是一個數字,
// 所以也必須寫在方括號里。
myObj[100] = "100";
2
3
4
5
6
7
8
9
10
傳統的作法是賦給陣列元素以 0 開始的數字索引。這些陣列元素與 length 屬性相互動。然而,由於所有的陣列也是對象,也支援 expando 屬性。請注意,雖然如此,expando 屬性並不以任何方式與 length 屬性相互動。例如:
// 三個元素的陣列
var myArray = new Array(3);
// 新增數據
myArray[0] = "Hello";
myArray[1] = 42;
myArray[2] = new Date(2000, 1, 1);
// 顯示陣列的長度 3
window.alert(myArray.length);
// 新增某些 expando 屬性
myArray.expando = "JScript!";
myArray["another Expando"] = "Windows";
// 仍然顯示 3,因為兩個 expando 屬性
// 並不影響長度。
window.alert(myArray.length);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
雖然 JScript 並不直接支援多維陣列,但是可以在陣列元素中儲存任意種類的數據 — 包含其他陣列。所以通過在另一個陣列的元素里儲存其他陣列可以得到多維陣列的特性。例如,下面的程式碼為最大為 5 的數字建立了乘法表:
// 若是更大的表請改變本數
var iMaxNum = 5;
// 循環計數
var i, j;
// 新陣列。由於陣列從 0 開始計數,
// 而不是 1,所以陣列大小為 iMaxNum + 1。
var MultiplicationTable = new Array(iMaxNum + 1);
// 為每個主要的數做循環(表中的每一行)
for (i = 1; i <= iMaxNum; i++) {
// 產生表中的列
MultiplicationTable[i] = new Array(iMaxNum + 1);
// 將乘法的結果存在行中
for (j = 1; j <= iMaxNum; j++) {
MultiplicationTable[i][j] = i * j;
}
}
window.alert(MultiplicationTable[3][4]); // 顯示 12
window.alert(MultiplicationTable[5][2]); // 顯示 10
window.alert(MultiplicationTable[1][4]); // 顯示 4
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 8.2. 建立自己的對象
要建立自己的對象實體,必須首先為其定義一個建構函式。建構函式建立一個新對象,賦予對像屬性,並在合適的時候賦予方法。例如,下面的示例為 pasta 對像定義了建構函式。注意 this 關鍵字的使用,它指向目前對象。
// pasta 是有四個參數的構造器。
function pasta(grain, width, shape, hasEgg) {
// 是用什麼糧食做的?
this.grain = grain;
// 多寬?(數值)
this.width = width;
// 橫截面形狀?(字串)
this.shape = shape;
// 是否加蛋黃?(boolean)
this.hasEgg = hasEgg;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
定義了對象構造器后,用 new 運算子建立對像實體。
var spaghetti = new pasta("wheat", 0.2, "circle", true);
var linguine = new pasta("wheat", 0.3, "oval", true);
2
可以給對像實體新增屬性以改變該實體,但是用相同的構造器產生的其他對像定義中並不包括這些屬性,而且除非你特意新增這些屬性那麼在其他實體中並不顯示出來。如果要將對像所有實體的附加屬性顯示出來,必須將它們新增到建構函式或構造器原型對像(原型在JScript高級文件中討論)中。
// spaghetti 的附加屬性。
spaghetti.color = "pale straw";
spaghetti.drycook = 7;
spaghetti.freshcook = 0.5;
var chowFun = new pasta("rice", 3, "flat", false);
// chowFun 對像或其他現有的 pasta 對像
// 都沒有新增到 spaghetti 對像
// 的三個新屬性。
// 將屬性『foodgroup』加到 pasta 原型對像
// 中,這樣 pasta 對象的所有實體都可以有該屬性,
// 包括那些已經產生的實體。
pasta.prototype.foodgroup = "carbohydrates"
// 現在 spaghetti.foodgroup、chowFun.foodgroup,等等
// 均包含值「carbohydrates」。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 8.2.1. 在定義中包含方法
可以在對象的定義中包含方法(函式)。一種方法是在引用別處定義的函式的建構函式中新增一個屬性。例如,下面的示例擴充上面定義的 pasta 建構函式以包含 toString 方法,該方法將在顯示對象的值時被呼叫。
// pasta 是有四個參數的構造器。
// 第一部分與上面相同。
function pasta(grain, width, shape, hasEgg) {
// 用什麼糧食做的?
this.grain = grain;
// 多寬?(數值)
this.width = width;
// 橫截面形狀?(字串)
this.shape = shape;
// 是否加蛋黃?(boolean)
this.hasEgg = hasEgg;
// 這裡新增 toString 方法(如下定義)。
// 注意在函式的名稱后沒有加圓括號;
// 這不是一個函式呼叫,而是
// 對函式自身的引用。
this.toString = pastaToString;
}
// 實際的用來顯示 past 對像內容的函式。
function pastaToString() {
// 返回對象的屬性。
return "Grain: " + this.grain + "\n" +
"Width: " + this.width + "\n" + "Shape: " + this.shape + "\n" +
"Egg?: " + Boolean(this.hasEgg);
}
var spaghetti = new pasta("wheat", 0.2, "circle", true);
// 將呼叫 toString() 並顯示 spaghetti 對像
// 的屬性(需要Internet 瀏覽器)。
window.alert(spaghetti);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 8.3. 內部對像
JScript 提供了 11 個內部(或「內建」)對象。它們是Array、Boolean、Date、Function、Global、Math、Number、Object、RegExp、Error 以及 String 對象。每一個對像有相關的方法和屬性,這在語言參考中有詳細的描述。本節中也描述了某些對象。
# 8.3.1. Array 對像
陣列下標可以被認為是對象的屬性,它是通過數字索引來引用的。注意新增到陣列中的已命名的屬性不能通過數字來索引;它們是與陣列元素分離的。
使用 new 運算子和 Array() 構造器 產生一個新的陣列,如下面的示例。
var theMonths = new Array(12);
theMonths[0] = "Jan";
theMonths[1] = "Feb";
theMonths[2] = "Mar";
theMonths[3] = "Apr";
theMonths[4] = "May";
theMonths[5] = "Jun";
theMonths[6] = "Jul";
theMonths[7] = "Aug";
theMonths[8] = "Sep";
theMonths[9] = "Oct";
theMonths[10] = "Nov";
theMonths[11] = "Dec";
2
3
4
5
6
7
8
9
10
11
12
13
用關鍵字 Array 產生陣列時,JScript 包含了 length 屬性,該屬性記錄了陣列入口數。如果沒有給該屬性指定值,則設定長度為 0 且陣列沒有入口點。如果指定一個數值,則將長度設定為該數。如果指定了不止一個參數,則這些參數被用作陣列的入口。另外,參數的數目被賦給 length 屬性。如下面的示例與前一個示例是等價的。
var theMonths = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
當向用關鍵字 Array 產生的陣列中新增元素時,JScript 自動改變屬性 length 的值。JScript 中的陣列索引總是以 0 開始,而不是 1,所以屬性 length 通常比陣列的最大索引大 1。
# 8.3.2. String對像
在 JScript 中,可以將字串(和數)當作對像來處理。string 對像 有一些內建方法,可以和自己的字串一起使用。其中一個是substring 方法,它返回字串的一部分。該方法以兩個數字作為參數。
aString = "0123456789";
var aChunk = aString.substring(4, 7); // 將 aChunk 設為 "456"。
var aNotherChunk = aString.substring(7, 4); // 將 aNotherChunk 設為 "456"。
// 使用上面產生陣列的示例:
firstLetter = theMonths[5].substring(0, 1); // 將變數 firstLetter 設為「J」。
2
3
4
5
String 對象的另一個屬性是 length 屬性。本屬性包含了字串中的字元數(空字串為 0)。它是一個數值,可以直接在計算中使用。
var howLong = "Hello World".length // 設定變數 howLong 為 11。
# 8.3.3. Math 對像
Math 對像有許多預定義屬性和方法。屬性是特殊的數字。這些特殊的數字之一是 pi 值(近似 3.14159…)。這是 Math.PI 屬性,如下例所示。
// 聲明一個半徑變數並賦數值。
var circleArea = Math.PI * radius * radius; // 注意 Math 和 PI 大寫。
2
Math 對象的一個內建方法是乘冪方法(或 pow),使用該方法求得指定數的冪次。下面的例子同時使用了 pi 和乘冪。
// 本公式計算給定半徑的球體的體積。
volume = (4/3)*(Math.PI*Math.pow(radius,3));
2
# 8.3.4. Date 對像
Date 對象可以被用來表示任意的日期和時間,獲取目前系統日期以及計算兩個日期的間隔。它擁有一些預定義的屬性和方法。通常,Date 對像給出星期;月份,天數和年份;以及以小時,分鐘和秒表示的時間。該資訊是基於 1970 年1 月 1 日 00:00:00.000 GMT 開始的毫秒數,其中 GMT 是格林威治標準時間(首選術語是 UTC,或者「全球標準時間」,它引用的訊號是由「世界時間標準」發佈的)。JScript 可以處理 250,000 B.C. 到 255,000 A.D範圍內的日期。
使用 new 運算子建立一個新的 Date 對象。下面的示例計算當年已過去的天數和今年剩下的天數。
var thisIsToday = new Date();
var toDay = new Date(); //獲取今天的日期。
// 提取年,月,日。
var thisYear = toDay.getFullYear();
var thisMonth = theMonths[toDay.getMonth()];
var thisDay = thisMonth + " " + toDay.getDate() + ", " + thisYear;
2
3
4
5
6
7
8
# 8.3.5. Number 對像
除了 Math 對像中可用的特殊數值屬性(例如 PI)外,在 Microsoft JScript 中, Number 對像有幾個其他的數值屬性。
屬性 | 描述 |
---|---|
MAX_VALUE | 可能的最大數大約為 1.79E+308;可以是正數或負數。(具體數值隨系統不同而有微小差別。) |
MIN_VALUE | 可能的最小數大約為 2.22E-308;可以是正數或負數。(具體數值隨系統不同而有微小差別。) |
NaN | 特殊非數量值,「不是數值」。 |
POSITIVE_INFINITY | 比最大正數(Number.MAX_VALUE)還要大的任意正值自動被轉換為此值,代表正無窮大。 |
NEGATIVE_INFINITY | 比最小的負數(負的 Number.MAX_VALUE)還小的任意值被自動轉換為此值,代表負無窮。 |
Number.NaN 是一個特殊的屬性,被定義為「不是數值」。例如被 0 除返回 NaN。試圖解析一個無法被解析為數字的字串同樣返回 Number.NaN。把 NaN 與任何數值或本身作比較的結果都是不相等。不能通過與 Number.NaN 比較來測試 NaN 結果,而應該使用 isNaN() 函式。
# 9. JScript 保留字
JScript 有一些保留字不能在識別符號中使用。保留字對 JScript 語言有特殊的含義,它們是語言語法的一部分。使用保留字在載入程式的時候將產生編譯錯誤。
JScript 還有一些留作將來使用的保留字。這些字不是現在的 JScript 語言的一部分,然而它們是為將來的使用保留的。
保留詞
break | delete | function | return | typeof |
case | do | if | switch | var |
catch | else | in | this | void |
continue | false | instanceof | throw | while |
debugger | finally | new | true | with |
default | for | null | try |
# 9.1. 為將來保留的詞
abstract | double | goto | native | static |
boolean | enum | implements | package | super |
byte | export | import | private | synchronized |
char | extends | int | protected | throws |
class | final | interface | public | transient |
const | float | long | short | volatile |
當選擇識別符號時避免使用已經在內部 JScript 對像或函式中使用的詞,如 String 或 parseInt。