JavaScript 完全实现了 ECMA 标准。本概述的目的就是引导您学习使用 JavaScript。
JavaScript 是一种解释型的、基于对象的脚本语言。尽管与 C++ 这样成熟的面向对象的语言相比,JavaScript 的功能要弱一些,但对于它的预期用途而言,JavaScript 的功能已经足够大了。
JavaScript 不是其他语言的精简版(例如,它只是与 Java 有点模糊而间接的关系),也不是任何事物的简化。不过,它有其局限性。例如,您不能使用该语言来编写独立运行的应用程序,并且没有对读写文件的内置支持。此外,JavaScript 脚本只能在某个解释器或“宿主”上运行,如 Active Server Pages(ASP)、Internet 浏览器或者 Windows 脚本宿主。
JavaScript 是一种宽松类型的语言。宽松类型意味着您不必显式定义变量的数据类型。事实上 JavaScript 更进一步。您无法在JScriot上明确地定义数据类型。此外,在大多数情况下,JavaScript 将根据需要自动进行转换。例如,如果将一个数值添加到由文本组成的某项(一个字符串),该数值将被转换为文本。
与其他许多编程语言一样, JavaScript 是用文本方式编写的,并被组织成为语句、由相关的语句集组成的块、以及注释。在一条语句内可以使用变量、比如字符串和数字(称为“文字”)的立即数、以及表达式。
JavaScript 程序是语句的集合。一条 JavaScript 语句相当于英语中的一个完整句。JavaScript 语句将表达式组合起来,完成一个任务。
一条语句由一个或多个表达式、关键字或者运算符(符号)组成。典型地,一条语句写一行,尽管一条语句可以超过两行或更多行。两条或更多条语句也可以写在同一行上,语句之间用分号“;”隔开。通常,每一新行开始一条新语句。不过显式地终止语句是一个好方法。这是用分号 (;)来实现的,分号是 JavaScript 语句的终止字符。下面给出 JavaScript 语句的两隔示例。
aBird = "Robin"; //将文本“Robin”赋值给变量aBirdvar today = new Date(); //将今天的日期赋值给变量today
用大括号({})括起来的一组 JavaScript 语句称为一个语句块。分组到一个语句块中的语句通常可当作单条语句处理。这就是说在 JavaScript 期望有一条单个语句的大多数地方可以使用语句块。应该注意以 for 和 while 打头的循环语句是例外情况。注意,语句块中的原始语句以分号结束,但语句块本身并不以分号结束。
通常,在函数和条件语句中使用语句块。注意,JavaScript 与 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;
单行的 JavaScript 注释以一对正斜杠(//)开始。下面给出一个单行注释的示例。
aGoodIdea = "Comment your code thoroughly."; // 这是一个单行注释。
多行注释以一个正斜杠加一个星号的组合(/*)开始,并以其逆向顺序 (*/)结束。
/*这是一个用来解释前面的代码语句的多行注释。 该语句将一个值赋给aGoodIdea变量。 用引号包含的这种值称为一个文字。 文字显式并直接包含信息; 而不是简接地引用信息。 (引号不属于该文字的内容。)*/
注意 如果您试图将一个多行注释插入到另一个中,JavaScript 不能按正常的方式解释生成的多行注释。标明嵌入的多行注释结束的 */ 被认为是整个多行注释的结尾。这就意味着嵌入多行注释之后的文本不再被认为是注释;相应地,它将被解释为 JavaScript 代码,并会产生语法错误。
建议将所有的注释写为单行注释的语句块。这样您以后就能够将大段的代码与多行注释区分开。
//这是另一种多行注释,写成一系列单行注释。//在执行完该语句后,可以使用aGoodIdea变量的名字来引用其内容,//如下一条语句那样,即采用连接操作将字符串文字添加到// aGoodIdea变量,以创建一个新的变量。var extendedIdea = aGoodIdea + " You never know when you'll have to figure out what it does.";
JavaScript 语句中使用等号 (=)给变量赋值:等号是赋值运算符。= 运算符左边的操作项总是一个 Lvalue。Lvalue 可以是:
= 运算符右边的操作项总是一个 Rvalue。Rvalues 可以是任何类型的一个任意值,包括表达式的值。下面给出一个 JavaScript 赋值语句的示例。
anInteger = 3;
JavaScript 编译器解释本语句的意义为:“将 3 赋给变量 anInteger”或“anInteger 的值为 3”。
确定您理解了 = 运算符(赋值)和 == 运算符(相等)的差异。在比较两个值是否相等时,应使用两个等于号 (==)。这些内容将在 控制程序的流程 中详细介绍。
JavaScript 表达式是指 JavaScript 解释器能够计算生成值的 JavaScript “短语”。这个值可以是任何有效的 JavaScript 类型 — 数字、字符串、对象,等等。最简单的表达式是文字。下面给出 JavaScript 文字表达式的一些示例。
3.9 //数字文字"Hello!" //字符串文字false //布尔文字null //文字空值 {x:1, y:2} //对象文字[1,2,3] //数组文字function(x){return x*x;} //函数文字
更多复杂的表达式中包含变量、函数、函数调用以及其他表达式。可以用运算符将表达式组合,创建复合表达式。运算符可以是:
+ //加法- //减法* //乘法/ //除法
下面给出 JavaScript 复合表达式的一些示例。
var anExpression = 3 * (4 / 5) + 6;
var aSecondExpression = Math.PI * radius * radius;
var aThirdExpression = aSecondExpression + "%" + anExpression;
var aFourthExpression = "(" + aSecondExpression + ") % (" + anExpression + ")";
任何编程语言中,用一块数据量化一个概念。
How old am I?
在 JavaScript 中,变量是给概念的名称;它代表了给出瞬间的值。当使用该变量时,实际是用的它所代表的数据。给出示例:
NumberOfDaysLeft = EndDate – TodaysDate;
机械的理解是使用变量来存储、得到并操作脚本中出现的所有的不同值。创建有意义的变量名称;便于别人理解脚本。
变量在脚本中的第一次出现是在声明中。变量在第一次用到时就设置于内存中,便于后来在脚本中引用。使用变量之前先进行声明。可以使用 var 关键字来进行变量声明。
var count; //单个声明。var count, amount, level; //用单个var关键字声明的多个声明。var count = 0, amount = 100; //一条语句中的变量声明和初始化。
如果在 var 语句中没有初始化变量,变量自动取 JavaScript 值 undefined。尽管并不安全,但声明语句中忽略 var 关键字是合法的 JavaScript 语法。这时,JavaScript 解释器给予变量全局范围的可见度。当在过程级中声明一个变量时,它不能用于全局范围;这种情况下,变量声明必须用 var 关键字。
变量名称是一个标识符。JavaScript 中,用标识符来:
JavaScript 是一种区分大小写的语言。因此变量名称 myCounter 和变量名称 mYCounter 是不一样的。变量的名称可以是任意长度。创建合法的变量名称应遵循如下规则:
下面给出合法变量名称的一些示例:
_pagecount
Part9
Number_Items
下面给出无效变量名称的一些示例:
99Balloons //不能以数字开头。Smith&Wesson //“与”符号(&)字符用于变量名称是无效的。
当要声明一个变量并进行初始化,但又不想指定任何特殊值,可以赋值为 JavaScript 值 null。下面给出示例。
var bestAge = null; var muchTooOld = 3 * bestAge; // muchTooOld的值为0。
如果声明了一个变量但没有对其赋值,该变量存在,其值为JavaScript 值 undefined。下面给出示例。
var currentCount; var finalCount = 1 * currentCount; // finalCount的值为NaN,因为currentCount为undefined。
注意在 JavaScript 中 null 和 undefined 的主要区别是 null 的操作象数字 0,而 undefined 的操作象特殊值NaN (不是一个数字)。对 null 值和 undefined 值作比较总是相等的。
可以不用 var 关键字声明变量,并赋值。这就是隐式声明。
noStringAtAll = ""; //隐式声明变量noStringAtAll。
不能使用未经过声明的变量。
var volume = length * width; //错误—length和width并不存在。
表达式中操作项的数据类型相同时 JavaScript 解释器才能对其求值。如果表达式不经过强制转换就试图对两个不同的数据类型(如一个为数字,另一个为字符串)执行运算,将产生错误结果。但在 JavaScript 中情况就不同了。
JavaScript 是一种自由类型的语言。它的变量没有预定类型(相对于强类型语言,如 C++)。相反,JavaScript 变量的类型相应于他们包含的值的类型。这种操作的好处是能将值作为另一类型处理。
在 JavaScript 中,可以对不同类型的值执行运算,不必担心 JavaScript 解释器产生异常。相反,JavaScript 解释器自动将数据类型之一改变(强制转换)为另一种数据类型,然后执行运算。例如:
| 运算 | 结果 |
|---|---|
| 数值与字符串相加 | 将数值强制转换为字符串。 |
| 布尔值与字符串相加 | 将布尔值强制转换为字符串。 |
| 数值与布尔值相加 | 将布尔值强制转换为数值。 |
考虑下面的示例。
var x = 2000; //一个数字。var y = "Hello"; //一个字符串。x = x + y; //将数字强制转换为字符串。document.write(x); //输出2000Hello。
要想显式地将字符串转换为整数,使用 parseInt 方法。要想显式地将字符串转换为数字,使用 parseFloat 方法。请注意,比较大小时字符串自动转换为相等的数字,但加法(连接)运算时保留为字符串。
JavaScript 有三种主要数据类型、两种复合数据类型和两种特殊数据类型。
主要(基本)数据类型是:
复合(引用)数据类型是:
特殊数据类型是:
一个字符串值是排在一起的一串零或零以上的 Unicode 字符(字母、数字和标点符号)。字符串数据类型用来表示 JavaScript 中的文本。脚本中可以包含字符串文字,这些字符串文字放在一对匹配的的单引号或双引号中。字符串中可以包含双引号,该双引号两边需加单引号,也可以包含单引号,该单引号两边需加双引号。下面是字符串的示例:
"Happy am I; from care I’m free!"
'"Avast, ye lubbers!" roared the technician.'
"42"
'c'
请注意,JavaScript 中没有表示单个字符的类型(如 C++ 的 char)。要表示 JavaScript 中的单个字符,应创建一个只包含一个字符的字符串。包含零个字符("")的字符串是空(零长度)字符串。
在 JavaScript 中整数和浮点值没有差别;JavaScript 数值可以是其中任意一种(JavaScript 内部将所有的数值表示为浮点值)。
整型值可以是正整数,负整数和 0。可以用 10 进制,8 进制和 16 进制来表示。在 JavaScript 中大多数字是用十进制表示的。加前缀“0”表示 8 进制的整型值,只能包含 0 到 7 的数字。前缀为“0”同时包含数字“8”或“9”的数被解释为十进制数。
加前缀“0x”(零和x|X)表示 16 进制整型值。可以包含数字 0 到 9,以及字母 A 到 F(大写或小写)。使用字母 A 到 F 表示十进制 10 到 15 的单个数字。就是说 0xF 与 15 相等,同时 0x10 等于 16。
八进制和十六进制数可以为负,但不能有小数位,同时不能以科学计数法(指数)表示。
浮点值为带小数部分的数。也可以用科学计数法来表示。这就是说,大写或小写“e”用来表示 10 的次方。JavaScript用数值表示的八字节 IEEE754 浮点标准。这意味着数字最大可以到±1.7976931348623157x10308,最小到±5x10-324。以“0”开始且包含小数点的数字被解释为小数浮点数。
注意以“0x”或“00”开始并包含小数点的数将发生错误。以下是 JavaScript 中数字的例子。
| 数字 | 描述 | 等价十进制数 |
|---|---|---|
| .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 (编译错误) |
另外,JavaScript包含特殊值数字。它们是:
尽管字符串和数字类型可以有无数不同的值,boolean 数据类型却只有两个值。它们是文字 true 和 false。Boolean值是一个真值,它表示一个状态的有效性(说明该状态为真或假)。
脚本中的比较通常得到一个 Boolean 结果。考虑下一行 JavaScript 代码。
y = (x == 2000);
这里要比较变量 x 的值是否与数字 2000 相等。如果相等,比较的结果为 Boolean 值 true,并将其赋给变量 y。如果x与2000不等,则比较的结果为boolean值false。
Boolean值在结构控制中尤其有用。可以将直接创建 boolean 值的比较与用使用该 boolean 值的语句相组合。考虑下面的JavaScript代码范例。
if (x == 2000)
z = z + 1;
else
x = x + 1;
当 boolean 值为 true 时,JavaScript 中的 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) // 这与上面的代码不同!
有关比较的详细信息,请参见控制程序的流程。
在 JavaScript 中数据类型 null 只有一个值:null。关键字 null 不能用作函数或变量的名称。
包含 null 的变量包含“无值”或“无对象”。换句话说,该变量没有保存有效的数、字符串、boolean、数组或对象。可以通过给一个变量赋 null 值来清除变量的内容。
请注意,在 JavaScript 中,null 与 0 不相等(与在 C 和 C++ 中不同)。同时应该指出的是,JavaScript中 typeof 运算符将报告 null 值为 Object 类型,而非类型 null。这点潜在的混淆是为了向下兼容。
如下情况使返回 undefined 值:
注意不能通过与 undefined 做比较来测试一个变量是否存在,虽然可以检查它的类型是否为“undefined”。在以下的代码范例中,假设程序员想测试是否已经声明变量 x :
//这种方法不起作用if (x == undefined)//作某些操作//这个方法同样不起作用-必须检查//字符串"undefined"if (typeof(x) == undefined)//作某些操作//这个方法有效if (typeof(x) == "undefined")//作某些操作
考虑将 undefined 值与null做比较。
someObject.prop == null;
如下情况时,比较的结果为 true,
if ("prop" in someObject) // someObject有属性'prop'
JavaScript 具有全范围的运算符,包括算术、逻辑、位、赋值以及其他某些运算符。
| 计算 | 逻辑 | 位运算 | 赋值 | 杂项 | |||||
|---|---|---|---|---|---|---|---|---|---|
| 描述 | 符号 | 描述 | 符号 | 描述 | 符号 | 描述 | 符号 | 描述 | 符号 |
| 负值 | - | 逻辑非 | ! | 按位取反 | ~ | 赋值 | = | 删除 | 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)//执行某些命令(将要运行的)。
JavaScript 脚本中的语句一般是按照写的顺序来运行的。这种运行称为顺序运行,是程序流的默认方向。
与顺序运行不同,另一种运行将程序流转换到脚本的另外的部分。也就是,不按顺序运行下一条语句,而是运行另外的语句。
要使脚本可用,该控制的转换必须以逻辑方式执行。程序控制的转换是基于一个“决定”,这个“决定”结果是真或假(返回 Boolean 型 true 或 false)。 创建一个表达式,然后测试其是否为真。主要有两种程序结构实现本功能。
第一种是选择结构。用来指明两种程序流方向,在程序中创建一个交叉点(像岔路)。在 JavaScript 中有四种选择结构可用。
第二种类型的程序控制结构是循环结构。使用循环结构来指明当某些条件保持为真时要重复的动作。当控制语句的条件得到满足时(通常在某些迭代的特定数字后),控制跳过循环结构传递到下条语句。在 JavaScript 中有四种循环结构可用。
通过嵌套和堆栈选择、循环控制结构,可以创建相当复杂的脚本。
第三种形式的结构程序流由意外处理给出,本文档不作讨论。
JavaScript 支持 if 和 if...else 条件语句。在 if 语句中将测试一个条件,如果该条件满足测试,执行相关的 JavaScript 编码。在 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!");}
JavaScript 也支持隐式的条件格式。该格式在要测试的条件后使用一个问号(而不是在条件前的 if )。它也指定两个可选项,一个在满足条件时使用,另一个在条件不满足时使用。这两个选择项之间必须用一个冒号隔开。
var hours = ""; //下面的代码指定hours是包含theHour的内容,//还是包含theHour - 12的内容。hours += (theHour >= 12) ? " PM" : " AM";
如果要一起测试多个条件,并且知道某个条件比其他条件更可能满足或不满足测试,可以使用称为“短路计算”的特性来加速脚本的运行速度。当 JavaScript 计算逻辑表达式时,只计算要得到结果所需的子表达式。
例如,如果有一个“与”表达式,如 ((x == 123) && (y == 42)),JavaScript 首先检查 x 是否为 123。如果不是,即使 y 等于 42,整个表达式的值也不可能为 true。因此,并不对 y 作测试,JavaScript 返回 false 值。
类似地,如果多个条件中只要有一个为真(使用 || 运算符),则当任何一个条件满足该测试时测试则停止。如果要测试的条件包括函数调用或其他复合表达式,这种处理方式就有效。出于此种想法,写 OR 表达式时,先写最有可能为 true 的条件。写 AND 表达式时,先写最有可能为 false 的条件。
以这种方式设计脚本的好处的一个示例是:在下例中如果 runfirst() 返回 0 或 false, 则不会运行 runsecond()。
if ((runfirst() == 0) || (runsecond() == 0)) {
// 若干代码。
}
有多种方式来重复执行一条语句或语句块。通常重复执行被称为循环或重复。重复只是循环的一个运行。典型情况是用一个变量测试来进行控制,每执行一次循环变量的取值都会更改。JavaScript 支持四种循环: for 循环、 for...in 循环、 while 循环、 do...while 循环。
for 语句指定了一个计数器变量,一个测试条件,以及更新该计数器的操作。在每次循环的重复之前,都将测试该条件。如果测试成功,将运行循环中的代码。如果测试不成功,不运循环中的代码,程序继续运行紧跟在循环后的第一行代码。在执行该循环后,计算机变量将在下一次循环之前被更新。
如果循环条件永不会满足,则不执行该循环。如果测试条件始终满足,则将导致无限循环。在有些情况下,前者可能是合乎需要的,而后者几乎没有用处,因此在编写循环条件时一定要注意。
/*更新表达式(下例中的"icount++")将在循环结束时被执行,即在构成循环主体的语句块被执行后,在测试条件之前。*/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;}
JavaScript 提供了一种特别的循环方式来遍历一个对象的所有用户定义的属性或者一个数组的所有元素。for...in 循环中的循环计数器是一个字符串,而不是数字。它包含当前属性的名称或者当前数组元素的下标。
下面的代码范例应在 Internet 浏览器中运行,因为它使用 alert 方法,该方法不属于 JavaScript。
//创建具有某些属性的对象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]);}
尽管 for...in 循环看起来像 VBScript 的 For Each...Next 循环,其实并不一样。JavaScript 的 for...in 循环重复JavaScript 对象所有的属性。VBScript 的 For Each...Next 循环重复集合中的所有项目。要循环 JavaScript 中的所有集合,需要用 Enumerator 对象。尽管某些对象(像 Internet 浏览器中的那些)支持 VBScript 的 For Each...Next 和 JavaScript 的 for...in 循环,但多数对象并不都支持。
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!");
注意 由于 while 循环没有显式的内置计数器变量,因此比其他类型的循环更容易产生无限循环。此外,由于不易发现循环条件是在何时何地被更新的,很容易编写一个实际上从不更新条件的 while 循环。因此在编写 while 循环时应特别小心。
同上面所提到的,在 JavaScript 中还有 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!");
在 JavaScript 中当某些条件得到满足时,用 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!");elsewindow.alert("Yep - it's the Ultimate Answer!");
JavaScript 函数执行操作,也可以返回值。某些时候是计算或比较的结果。函数又被称为“全局方法”。
一个函数中包含有几个操作。这样可使得代码更合理化。可以写一组语句并给其命名,然后通过调用它并传递其需要的信息来运行整组语句。
给函数传递信息可以把信息放在函数名称后面的圆括号中。传递给函数的信息称作参数。某些函数根本不带任何参数,而其他函数带一个或者多个参数。在某些函数中,参数的个数取决于如何使用该函数。
JavaScript 支持两种函数:一类是语言内部的函数,另一类是自己创建的。
JavaScript 语言包含很多内部函数。某些函数可以操作表达式和特殊字符,而其他函数将字符串转换为数值。一个有用的内部函数是 eval()。该函数可以对以字符串形式表示的任意有效的 JavaScript代码求值。eval() 函数有一个参数,该参数就是想要求值的代码。下面给出一个使用本函数的示例。
var anExpression = "6 * 9 % 7"; var total = eval(anExpression); //将变量total赋值为5。var yetAnotherExpression = "6 * (9 % 7)";total = eval(yetAnotherExpression) //将变量total赋值为12。//将一个字符串赋给totality(注意嵌套引用)var totality = eval("’...surrounded by acres of clams.’");
有关内部函数的详细信息请参考语言参考。
在必要的时候,可以创建并使用自己的函数。一个函数的定义中包含了一个函数语句和一个 JavaScript 语句块。
下面示例中的 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和bif (b > a){d = a;a = b;b = d;}//需要的话交换a和cif (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);
JavaScript 对象是属性和方法的集合。一个方法就是一个函数,是对象的成员。属性是一个值或一组值(以数组或对象的形式),是对象的成员。JavaScript 支持四种类型的对象:内部对象、生成的对象、宿主给出的对象(如 Internet 浏览器中的 window 和 document)以及 ActiveX 对象(外部组件)。
在 JavaScript 中,对象和数组几乎是以相同的方式处理的。对象和数组均可以被赋予任意值,实际上数组只是一种特殊的对象。数组和对象的区别在于数组有一个“奇妙的” length 属性,而对象没有。这意味着可以给数组的一个元素赋予比其他元素更大的值。例如,myArray[100] = "hello" — 然后 length 属性将自动地被更新为 101(新长度)。同样,如果修改数组的 length 属性,将删除不再是数组部分的元素。
JavaScript 中所有的对象均支持“expando”属性或那些可以在运行时动态添加和删除的属性。这些属性可以有包含数字的任意名称。如果属性的名称是简单的标识符<<参考标识符规则>>,可以在对象名称的后面加句点,例如:
var myObj = new Object(); //添加两个expando属性,'name'和'age'myObj.name = "Fred";myObj.age = 42;
如果属性名称不是一个简单的标识符,或者在写脚本的时候不知道,可以在方括号中使用任意表达式来索引属性。在 JavaScript 中所有 expando 属性的名称在被添加到对象之前被转换为字符串。
var myObj = new Object(); //添加两个无法写在object.property语//法中的expando属性。//第一个属性包含无效字符(空格),//所以必须写在方括号里。myObj["not a valid identifier"] = "This is the property value";//第二个expando名称是一个数字,//所以也必须写在方括号里。myObj[100] = "100";
传统的作法是赋给数组元素以 0 开始的数字索引。这些数组元素与 length 属性相交互。然而,由于所有的数组也是对象,也支持 expando 属性。请注意,虽然如此,expando 属性并不以任何方式与 length 属性相交互。例如:
//三个元素的数组var myArray = new Array(3);//添加数据myArray[0] = "Hello";myArray[1] = 42;myArray[2] = new Date(2000, 1, 1);//显示数组的长度3window.alert(myArray.length);//添加某些expando属性myArray.expando = "JavaScript!";myArray["another Expando"] = "Windows";//仍然显示3,因为两个expando属性//并不影响长度。window.alert(myArray.length);
虽然 JavaScript 并不直接支持多维数组,但是可以在数组元素中存储任意种类的数据 — 包含其他数组。所以通过在另一个数组的元素里存储其他数组可以得到多维数组的特性。例如,下面的代码为最大为 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]); //显示12window.alert(MultiplicationTable[5][2]); //显示10window.alert(MultiplicationTable[1][4]); //显示4
JavaScript 有一些保留字不能在标识符中使用。保留字对 JavaScript 语言有特殊的含义,它们是语言语法的一部分。使用保留字在加载脚本的时候将产生编译错误。
JavaScript 还有一些留作将来使用的保留字。这些字不是现在的 JavaScript 语言的一部分,然而它们是为将来的使用保留的。
保留词
| 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 |
| 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 |
当选择标识符时避免使用已经在内部 JavaScript 对象或函数中使用的词,如 String 或 parseInt。
构造函数是一个函数,调用它来例示并初始化特殊类型的对象。可以使用 new 关键字来调用一个构造函数。下面给出了使用构造函数的新示例。
var myObject = new Object(); //创建没有属性的通用对象。var myBirthday = new Date(1961, 5, 10); //创建一个Date对象。var myCar = new Car(); //创建一个用户定义的对象,并初始化其属性。
通过构造函数将一个参数作为特定的 this 关键字的值传递给新创建的空对象。然后构造函数负责为新对象执行适应的初始化(创建属性并给出其初始值)。完成后,构造函数返回它所构造的对象的一个参数。
可以使用 new 运算符结合像 Object()、Date() 和 Function() 这样的预定义的构造函数来创建对象并对其初始化。面向对象的编程其强有力的特征是定义自定义构造函数以创建脚本中使用的自定义对象的能力。创建了自定义的构造函数,这样就可以创建具有已定义属性的对象。下面是自定义函数的示例(注意 this 关键字的使用)。
function Circle (xPoint, yPoint, radius) { this.x = xPoint; //圆心的x坐标。this.y = yPoint; //圆心的y坐标。this.r = radius; //圆的半径。 }
调用 Circle 构造函数时,给出圆心点的值和圆的半径(所有这些元素是完全定义一个独特的圆对象所必需的)。结束时 Circle 对象包含三个属性。下面是如何例示 Circle 对象。
var aCircle = new Circle(5, 11, 99);
在编写构造函数时,可以使用原型对象(它本身是所有构造函数的一个属性)的属性来创建继承属性和共享方法。原型属性和方法将按引用复制给类中的每个对象,因此它们都具有相同的值。可以在一个对象中更改原型属性的值,新的值将覆盖默认值,但仅在该实例中有效。属于这个类的其他对象不受此更改的影响。下面给出了使用自定义构造函数的示例,Circle(注意 this 关键字的使用)。
Circle.prototype.pi = Math.PI; function ACirclesArea () { return this.pi * this.r * this.r; //计算圆面积的公式为?r2。 }Circle.prototype.area = ACirclesArea; //计算圆面积的函数现在是Circle Prototype对象的一个方法。var a = ACircle.area(); //此为如何在Circle对象上调用面积函数。
使用这个原则,可以给预定义的构造函数(都具有原型对象)定义附加属性。例如,如果想要能够删除字符串的前后空格(与 VBScript 的 Trim 函数类似),就可以给 String 原型对象创建自己的方法。
//增加一个名为trim的函数作为// String构造函数的原型对象的一个方法。String.prototype.trim = function(){//用正则表达式将前后空格//用空字符串替代。return this.replace(/(^\s*)|(\s*$)/g, "");}//有空格的字符串var s = " leading and trailing spaces ";//显示" leading and trailing spaces (35)"window.alert(s + " (" + s.length + ")");//删除前后空格s = s.trim();//显示"leading and trailing spaces (27)"window.alert(s + " (" + s.length + ")");
递归是一种重要的编程技术。该方法用于让一个函数从其内部调用其自身。一个示例就是计算阶乘。0 的阶乘被特别地定义为 1。 更大数的阶乘是通过计算 1 * 2 * ...来求得的,每次增加 1,直至达到要计算其阶乘的那个数。
下面的段落是用文字定义的计算阶乘的一个函数。
“如果这个数小于零,则拒绝接收。如果不是一个整数,则将其向下舍入为相邻的整数。如果这个数为 0,则其阶乘为 1。如果这个数大于 0,则将其与相邻较小的数的阶乘相乘。”
要计算任何大于 0 的数的阶乘,至少需要计算一个其他数的阶乘。用来实现这个功能的函数就是已经位于其中的函数;该函数在执行当前的这个数之前,必须调用它本身来计算相邻的较小数的阶乘。这就是一个递归示例。
递归和迭代(循环)是密切相关的 — 能用递归处理的算法也都可以采用迭代,反之亦然。确定的算法通常可以用几种方法实现,您只需选择最自然贴切的方法,或者您觉得用起来最轻松的一种即可。
显然,这样有可能会出现问题。可以很容易地创建一个递归函数,但该函数不能得到一个确定的结果,并且不能达到一个终点。这样的递归将导致计算机执行一个“无限”循环。下面就是一个示例:在计算阶乘的文字描述中遗漏了第一条规则(对负数的处理) ,并试图计算任何负数的阶乘。这将导致失败,因为按顺序计算 -24 的阶乘时,首先不得不计算 -25 的阶乘;然而这样又不得不计算 -26 的阶乘;如此继续。很明显,这样永远也不会到达一个终止点。
因此在设计递归函数时应特别仔细。如果怀疑其中存在着无限递归的可能,则可以让该函数记录它调用自身的次数。如果该函数调用自身的次数太多,即使您已决定了它应调用多少次,就自动退出。
下面仍然是阶乘函数,这次是用 JavaScript 代码编写的。
//计算阶乘的函数。如果传递了//无效的数值(例如小于零),//将返回-1,表明发生了错误。若数值有效,//把数值转换为最相近的整数,并//返回阶乘。function factorial(aNumber) {aNumber = Math.floor(aNumber); //如果这个数不是一个整数,则向下舍入。if (aNumber < 0) { //如果这个数小于0,拒绝接收。return -1;}if (aNumber == 0) { //如果为0,则其阶乘为1。return 1;}else return (aNumber * factorial(aNumber - 1)); //否则,递归直至完成。 }
JavaScript 有两种变量范围:全局和局部。如果在任何函数定义之外声明了一个变量,则该变量为全局变量,且该变量的值在整个持续范围内都可以访问和修改。如果在函数定义内声明了一个变量,则该变量为局部变量。每次执行该函数时都会创建和破坏该变量;且它不能被该函数外的任何事物访问。
像 C++ 这样的语言也有“块范围”。在这里,任何一对“{}”都定义新的范围。JavaScript 不支持块范围。
一个局部变量的名称可以与某个全局变量的名称相同,但这是完全不同和独立的两个变量。因此,更改一个变量的值不会影响另一个变量的值。在声明局部变量的函数内,只有该局部变量有意义。
var aCentaur = "a horse with rider,"; // aCentaur的全局定义。// JavaScript代码,为简洁起见有省略。function antiquities() //在这个函数中声明了一个局部aCentaur变量。 {// JavaScript代码,为简洁起见有省略。var aCentaur = "A centaur is probably a mounted Scythian warrior";// JavaScript代码,为简洁起见有省略。aCentaur += ", misreported; that is, "; //添加到局部变量。// JavaScript代码,为简洁起见有省略。 }//函数结束。var nothinginparticular = antiquities();aCentaur += " as seen from a distance by a naive innocent.";/*在函数内,该变量的值为"A centaur is probably a mounted Scythian warrior,misreported; that is, ";在函数外,该变量的值为这句话的其余部分:"a horse with rider, as seen from a distance by a naive innocent."*/
很重要的一点是注意变量是否是在其所属范围的开始处声明的。有时这会导致意想不到的情况。
tweak(); var aNumber = 100; function tweak() { var newThing = 0; //显式声明newThing变量。//本语句将未定义的变量赋给newThing,因为已有名为aNumber的局部变量。newThing = aNumber;//下一条语句将值42赋给局部的aNumber。aNumber = 42;if (false) {var aNumber; //该语句永远不会执行。aNumber = 123; //该语句永远不会执行。} //条件语句结束。 }//该函数定义结束。
当 JavaScript 运行函数时,首先查找所有的变量声明,
var someVariable;
并以未定义的初始值创建变量。如果变量被声明时有值,
var someVariable = "something";
那么该变量仍以未定义的值初始化,并且只有在运行了声明行时才被声明值取代,假如曾经被声明过。
JavaScript 在运行代码前处理变量声明,所以声明是位于一个条件块中还是其他某些结构中无关紧要。JavaScript 找到所有的变量后立即运行函数中的代码。如果变量是在函数中显式声明的 — 也就是说,如果它出现于赋值表达式的左边但没有用 var 声明 — 那么将把它创建为全局变量。
在 JavaScript 中,对数据的处理取决于该数据的类型。
Numbers 和 Boolean 类型的值 (true 和 false) 是按值来复制、传递和比较的。当按值复制或传递时,将在计算机内存中分配一块空间并将原值复制到其中。然后,即使更改原来的值,也不会影响所复制的值(反过来也一样),因为这两个值是独立的实体。
对象、数组以及函数是按引用来复制、传递和比较的。 当按地址复制或传递时,实际是创建一个指向原始项的指针,然后就像拷贝一样来使用该指针。如果随后更改原始项,则将同时更改原始项和复制项(反过来也一样)。实际上只有一个实体;“复本”并不是一个真正的复本,而只是该数据的又一个引用。
当按引用比较时,要想比较成功,两个变量必须参照完全相同的实体。例如,两个不同的 Array 对象即使包含相同的元素也将比较为不相等。要想比较成功,其中一个变量必须为另一个的参考。要想检查两个数组是否包含了相同的元素,比较 toString() 方法的结果。
最后,字符串是按引用复制和传递的,但是是按值来比较的。请注意,假如有两个 String 对象(用 new String("something") 创建的),按引用比较它们,但是,如果其中一个或者两者都是字符串值的话,按值比较它们。
注意 鉴于 ASCII和 ANSI 字符集的构造方法,按序列顺序大写字母位于小写字母的前面。例如 "Zoo" 小于 "aardvark"。如果想执行不区分大小写的匹配,可以对两个字符串调用 toUpperCase() 或 toLowerCase()。
按值传递一个参数给函数就是制作该参数的一个独立复本,即一个只存在于该函数内的复本。即使按引用传递对象和数组时,如果直接在函数中用新值覆盖原先的值,在函数外并不反映新值。只有在对象的属性或者数组的元素改变时,在函数外才可以看出。
例如(使用 IE 对象模式):
//本代码段破坏(覆盖)其参数,所以//调用代码中反映不出变化。function Clobber(param){//破坏参数;在调用代码中//看不到。param = new Object();param.message = "This will not work";}//本段代码改变参数的属性,//在调用代码中可看到属性改变。function Update(param){//改变对象的属性;//可从调用代码中看到改变。param.message = "I was changed";}//创建一个对象,并赋给一个属性。var obj = new Object();obj.message = "This is the original";//调用Clobber,并输出obj.message。注意,它没有发生变化。Clobber(obj);window.alert(obj.message); //仍然显示"This is the original"。//调用Update,并输出obj.message。注意,它已经被改变了。Update(obj);window.alert(obj.message); //显示"I was changed"。
当按值进行检验时,是比较两个截然不同的项以查看它们是否相等。通常,该比较是逐字节进行的。当按引用进行检验时,是看这两项是否是指向同一个原始项的指针。如果是,则比较结果是相等;如果不是,即使它们每个字节都包含完全一样的值,比较结果也为不相等。
按引用复制和传递字符串能节约内存;但是由于在字符串被创建后不能进行更改,因此可以按值进行比较。这样可以检查两个字符串是否包含相同的内容,即使它们是完全独立产生的。
JavaScript 中的数组是稀疏的。也就是说,如果一个数组具有三个元素,编号分别为 0、1 和 2,您就可以创建元素 50,而不必担心从 3 到 49 的参数。如果该数组有一个自动的 length 变量,(请参阅内部对象了解有关数组长度的自动监控的说明),该 length 变量被设为 51,而不是 4。当然您可以创建各元素的编号之间没有间隙的数组,不过没有必要这样做。
在 JavaScript 中,对象和数组几乎相同。两个主要差别是对象没有自动长度属性,而数组没有对象的属性和方法。
使用方括号“[]”来寻址数组。方括号中是一个数值或一个值为整数的表达式。下面的示例假定在脚本的其他地方已定义了entryNum 变量,且已赋值。
theListing = addressBook[entryNum];
theFirstLine = theListing[1];
通常,使用点运算符“.”访问对象的属性。例如,
myObject.aProperty
在这里,属性名称是一个标识符。也可以用索引运算符“[]”访问对象的属性。在这里,是把对象看作一个关联数组。关联数组是一种数据结构,它可以动态地将任意的数据的值与任意的字符串相关联。例如,
myObject["aProperty"] // 与上面相同。
尽管索引运算符更多地用于访问数组元素,当用于对象时,索引总是以字符串文字表示的属性名称。
注意访问对象属性的两种方法的重要差异。
| 运算符 | 属性名称作为 | 对属性名称的处理 |
|---|---|---|
| 点“.” | 标识符 | 不能作为数据处理 |
| 索引“[]” | 字符串文字 | 能被作为数据处理 |
在运行之前并不知道属性名称时,这个差异会有用(比如基于用户输入构造对象时)。要想从一个关联数组提取所有的属性,必须用 for … in 循环。
JavaScript 提供了一些特殊字符,允许在字符串中包括一些无法直接键入的字符。每个字符都以反斜杠开始。反斜杠是一个转义字符,表示 JavaScript 解释器下面的字符为特殊字符。
| 转义序列 | 字符 |
|---|---|
| \b | 退格 |
| \f | 走纸换页 |
| \n | 换行 |
| \r | 回车 |
| \t | 横向跳格 (Ctrl-I) |
| \' | 单引号 |
| \" | 双引号 |
| \\ | 反斜杠 |
请注意,由于反斜杠本身用作转义符,因此不能直接在脚本中键入一个反斜杠。如果要产生一个反斜杠,必须一起键入两个反斜杠 (\\)。
| 描述 | 语言要素 |
|---|---|
| 将两个数相加或连接两个字符串。 | 加法运算符(+) |
| 将一个值赋给变量。 | 赋值运算符(=) |
| 对两个表达式执行按位与操作。 | 按位与运算符(&) |
| 将一个表达式的各位向左移。 | 按位左移运算符(<<) |
| 对一个表达式执行按位取非(求非)操作。 | 按位取非运算符(~) |
| 对两个表达式指定按位或操作。 | 按位或运算符(|) |
| 将一个表达式的各位向右移,保持符号不变。 | 按位右移运算符(>>) |
| 对两个表达式执行按位异或操作。 | 按位异或运算符(^) |
| 使两个表达式连续执行。 | 逗号运算符(,) |
| 返回 Boolean 值,表示比较结果。 | 比较运算符 |
| 复合赋值运算符列表。 | 复合赋值运算符 |
| 根据条件执行两个表达式之一。 | 条件(三元)运算符(?:) |
| 将变量减一。 | 递减运算符(--) |
| 删除对象的属性,或删除数组中的一个元素。. | delete 运算符 |
| 将两个数相除并返回一个数值结果。 | 除法运算符(/) |
| 比较两个表达式,看是否相等。 | 相等运算符(==) |
| 比较两个表达式,看一个是否大于另一个。 | 大于运算符(>) |
| 比较两个表达式,看一个是否大于等于另一个。 | 大于等于运算符(>=) |
| 比较两个表达式,看是否值相等并具有相同的数据类型。 | 严格相等运算符(===) |
| 给变量加一。 | 递增运算符(++) |
| 比较两个表达式,看是否不相等。 | 不等运算符(!=) |
| 返回一个 Boolean 值,表明某个对象是否为特定类的一个实例。 | instanceof 运算符 |
| 比较两个表达式,看是否一个小于另一个。 | 小于运算符(<) |
| 比较两个表达式,看是否一个小于等于另一个。 | 小于等于运算符(<=) |
| 对两个表达式执行逻辑与操作。 | 逻辑与运算符(&&) |
| 对表达式执行逻辑非操作。 | 逻辑非运算符(!) |
| 对两个表达式执行逻辑或操作。 | 逻辑或运算符(||) |
| 将两个数相除,并返回余数。 | 取模运算符(%) |
| 将两个数相乘。 | 乘法运算符(*) |
| 创建一个新对象。 | new 运算符 |
| 比较两个表达式,看是否具有不相等的值或数据类型不同。 | 非严格相等运算符(!==) |
| 包含 JavaScript 运算符的执行优先级信息的列表。 | 运算符优先级 |
| 对两个表达式执行减法操作。 | 减法运算符(-) |
| 返回一个表示表达式的数据类型的字符串。 | typeof 运算符 |
| 表示一个数值表达式的相反数。 | 一元取相反数运算符(-) |
| 在表达式中对各位进行无符号右移。 | 无符号右移运算符(>>>) |
| 避免一个表达式返回值。 | void 运算符 |