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。