4.5.2 JavaScript的语法基础
编程语言的核心都需要描述这门语言基本的工作原理,包括基本语法规则、数据类型、运算符、内置功能等内容。ECMAScript规定了JavaScript的核心语法基础。
1.基本语法规则
JavaScript代码基于Unicode字符集,几乎支持现有所有语言,其语法借鉴了C语言及其他类语言(如Java和Perl)的语法。
(1)标识符
标识符是指变量、函数、属性的名字或函数的参数等,其组合规则为:第1个字符必须是字母、下划线(_)、美元符号($),而其他字符可以是字母、下划线、美元符号或数字。
(2)区分大小写
JavaScript代码是大小写敏感的,变量、函数名和操作符都需要区分大小写。例如,变量book和Book是两个不同的标识符。
(3)空格与换行
代码中多余的空格会被忽略,同一个标识符的所有字母必须连续。多数情况下,JavaScript中的换行符也会被忽略。
(4)语句分隔
ECMAScript中的语句以一个分号结尾。如果省略分号,则由解析器确定语句的结尾,但不推荐这种做法。
(5)注释
可以在JavaScript中添加注释来对代码进行解释,以提高代码的可读性。单行注释以//开头;多行注释则用/*表示开始,*/表示结束。JavaScript不会执行注释。
(6)保留字
JavaScript中规定了一组具有特定用途的关键字,例如,this、int、if、else、do等,用于表示控制语句,或用于执行特定操作,不能用作标识符。
2.数据类型、变量与常量
(1)数据类型
在编程语言中,数据类型是能够表示并操作的值的类型。JavaScript包括5种基本的数据类型:数值类型(Number)、布尔类型(Boolean)、字符串类型(String)、Undefined类型(Undefined)、Null类型(Null),以及1种复杂数据类型:对象类型(Object)。
①数值类型
JavaScript中用于表示数字的类型称为数值类型,可以表示整数或浮点数。整数数值可以由十进制、八进制和十六进制表示。例如,
浮点数值必须包含小数点,且小数点后必须至少有一位数字。数字的值可以用普通的记法也可以使用科学计数法。例如,
由于内存的限制,在大多数浏览器中ECMAScript能够表示的数值大约位于5e—324和1.797 693 134 862 315 7e+308之间。如果某个数值超出了该范围,将被自动转换成特殊的Infinity值。
NaN,即非数值(Not a Number),是一个特殊的数值,用于表示一个本来要返回数值的操作数但未返回数值的情况,以免影响其他代码的执行。
②布尔类型
布尔类型只有2个值:true和false(注意区分大小写),常用于判断表达式的逻辑条件。所有类型的值都有与这2个布尔值等价的值。要将一个值转换为其对应的布尔值,可以调用转型函数Boolean()。其转换规则如表4-8所示。
表4-8 一个值转换为其对应的布尔值的规则
③字符串类型
字符串类型用于表示字符序列或字符串。字符串可以由双引号(“)或单引号()表示,例如,
④Undefined类型
Undefined类型只有一个值,即undefined。在使用var声明变量但未对其初始化时,这个变量的值就是undefined。例如,
⑤Null类型
Null类型也只有一个特殊的值,即null,用于表示一个空对象指针。如果定义一个用于保存对象的变量,可以将其初始化为null。
⑥对象类型
ECMAScript中的对象其实就是一组属性和方法的集合。属性是描述对象特征的值,方法是能够在对象上执行的操作。
对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式来定义。属性由逗号分隔:
var member={name:“Alice“,pwd:“123“,id:1210};
上面例子中的会员对象(member)有3个属性:name、pwd以及id,表示会员的姓名、密码和ID号。
对象也可以有方法,方法是保存在对象属性中的JavaScript函数,用于访问操作对象的属性。如member.add()、member.delete()、member.update()表示增加会员、删除会员、更新会员。
(2)变量
变量是用来临时存储数值的容器,在程序运行过程中值可以发生改变。变量在命名时可以采用任意长度,但应遵守标识符的规则。
变量的定义有以下两种方式。
①使用var操作符对变量进行声明
可以一次声明一个变量,也可以同时声明多个变量,变量之间用逗号相隔。另外在声明变量时,也可以赋予变量初始值。例如,
②不对变量进行声明,直接赋初值
例如,
x=1;
根据作用范围不同,变量可分为全局变量和局部变量。函数外部直接定义的变量称为全局变量,在整个程序范围内都有效。函数内部定义的变量称为局部变量,作用范围仅限于变量所在的函数内。
ECMAScript的变量是松散类型的,可以用来保存任何类型的数据。这意味着相同的变量可用作不同的类型,例如,
(3)常量
根据不同的数据类型,常量也分为字符串类型、布尔类型、数值类型和null类型等。常量直接在语句中使用,值不会改变。
3.运算符和表达式
表达式是JavaScript中的一个短语,这个短语可以判断或者产生一个值。表达式可以作为参数传递给函数,或将表达式结果赋给变量保存起来。表达式是由操作数和运算符组成的。操作数是表达式中的常量、变量或子表达式,用于提供计算用的数据。常量、变量名可以看作最简单的一类表达式,常量表达式返回的值为它本身,变量表达式返回的值为变量的值,例如,
复杂表达式是由简单表达式通过运算符组合而成的。例如,
运算符是指程序设计语言中有运算意义的符号。运算符按照特定的运算规则对常量或变量进行运算,并计算出新值。通常运算符由符号,如+、*、|等,或关键字,如delete、var等来表示。JavaScript的运算符包含算术运算符、字符串运算符、关系运算符、赋值运算符、逻辑运算符、位运算符和一些特殊的运算符等。表4-9罗列了常见的JavaScript的运算符及其说明。
表4-9 常见的JavaScript的运算符及其说明
续表
当不同运算符组合在一起时,由运算符优先级来确定运算顺序。具有较高优先级的运算符先于具有较低优先级的运算符得到执行。同等级的运算符按从左到右的顺序进行。
4.语句
JavaScript的代码由语句、语句块和注释构成。JavaScript语句包含一个或多个表达式、关键字和运算符,用以完成某项任务。语句以分号(;)来表示该句的结束。多条语句还可以组合起来形成一种复合语句,称为语句块(blocks),通常用{}括起来。在下面的例句中,{}中间的两句语句就构成了一个语句块。
多数情况下语句块可被视为单个语句组合被其他JavaScript代码调用。
一个Javascript程序实际就是一个语句的集合,包括各种类型的语句,如把表达式当作语句用的表达式语句,声明变量函数的声明语句,控制代码执行顺序的条件语句、循环语句、跳转语句等。下面对常见的几类语句做简要介绍。
(1)表达式语句
表达式语句是JavaScript中最简单的语句。这类语句一般按从上到下的顺序依次执行。例如,
(2)声明语句
var和function语句都是声明语句,分别用来声明、定义变量和函数。这些语句用于定义标识符(变量名、函数名)并给它们赋值,以便在程序的其他地方使用。
var语句可以声明一个或多个变量,语法如下。
var name1[=value1][,…,namen=[valuen]];
var关键字后面跟的是要声明的变量列表,列表中每一个变量都可以带初始化表达式用于指定初值。如果没有指定初始化表达式,则初值为undefined。
function语句用来定义函数,具体语法结构及用法见本节“5.函数”部分的介绍。
(3)条件语句
条件语句是指根据条件,即判断指定表达式的值,来选择一个任务分支的语句。主要包括if/else语句、switch语句。
①if语句
if语句是一种基本的控制语句,使程序可以选择执行路径,有条件地执行语句。这类语句包括两种形式。第1种是
这种形式需要测试表达式的值,结果为真则执行语句组,否则不执行。第2种形式引入else从句,语法如下。
if-else语句提供了双路选择功能,测试表达式的值为假时则执行语句组2。
当代码中有多条分支时,可以使用else if语句,将多个if-else组合起来,语法如下。
②switch语句
当所有分支都依赖于同一个表达式时,使用if-else语句会重复计算多条if语句,效率比较低。此时可以选择switch语句,实现多路选择功能,在给定的多个选择中选择一个符合条件的分支来执行,语法如下。
执行语句时,首先计算表达式的值,然后查找case子句中的标识是否和表达式的值相同,如果找到匹配的case,则执行对应的语句组,如果没找到,则执行default对应的代码。如果没有default标识,则跳过所有代码。上述代码中每个case语句块都使用break语句结尾,表示switch语句结束,防止一个case语句块执行完后继续执行下一个case语句块。break语句将在后面介绍。
(4)循环语句
循环语句可以使一段代码重复执行,形成一个程序路径的回路。常用的循环语句包括while、do-while、for和for-in语句。
①while语句
while语句的语法如下。
while循环在执行循环体前测试条件表达式,如果条件成立则进入循环体,执行循环体的语句组,然后再次测试表达式,这种循环会一直持续,直到表达式的值为假。若条件不成立,则跳到循环后的第一条语句。
②do-while语句
do-while循环与while循环相似,不同之处在于do-while语句先执行一遍循环体,然后在循环体的尾部而不是顶部测试表达式,如果表达式成立则继续执行下一轮循环,否则跳到dowhile代码段后的第一条语句,语法如下。
do{
语句组;
}whi le(条件表达式);
③for语句
for语句提供了一种比while语句更方便的循环控制结构,语法如下。
for(初始化计数器;测试计数器;更新计数器){
语句组;
}
for循环语句指定了3个表达式分别表示初始化一个计数器变量、循环条件判断和计数器变量的更新,之间用分号分隔。在循环开始前初始化变量,然后每次循环执行之前,都要测试计数器的值。如果满足循环条件,则执行循环内的代码;如果测试不成功,则不执行循环内的代码,而是执行紧跟在循环后的第一行代码。当执行该循环时,计数器变量在下次重复循环前被更新。
④for-in语句
for-in语句是for语句的一个变体,语法如下。
for(n in set){
语句组;
}
其中n通常是一个变量名,也可以是一个可以产生左值的表达式或通过var语句声明的变量。set是一个表达式,其计算结果是一个对象。在执行语句过程中,先计算表达式,如果表达式为null或undefined,则会跳过循环并执行后续代码。如果表达式本身是一个对象,则依次枚举对象的属性来执行循环,在每次循环前,会先计算表达式的值,将属性名(一个字符串)赋给它。for-in语句提供了一种特别的循环方式来遍历一个对象的所有用户定义的属性或者一个数组的所有元素。例如,
上述代码执行完毕后,info中包含字符串Alice1235678。
(5)跳转语句
跳转语句使程序的执行从一个位置跳转到另一个位置,主要包括break、continue、return语句。
①break语句
break语句可以单独使用,其作用是跳出最内层循环或switch语句,语法如下。
break;
JavaScript也允许break后面跟随一个标签,语法如下。
break标签名;
此时程序将跳转到标签标识的语句块的结束位置。JavaScript中的语句可以添加标签,标签由加在语句前面的标签名和冒号标明,例如,标签名:语句。给语句定义标签后,就可以在程序的其他地方通过标签引用该语句。break和continue语句是唯一可以使用语句标签的语句。
②continue语句
和break语句类似,不过它不是退出循环,而是转去执行下一次循环。语法和break语句一样,既可以单独使用,也可以带有标签。如
cont inue;
cont inue标签名;
③return语句
return语句是函数调用后的返回值,语法如下。
return表达式;
该语句只能出现在函数内部。当执行到return语句时,函数终止执行并将表达式的值返回给调用程序。return语句也可以单独使用,此时函数向调用程序返回undefined。
(6)异常处理语句
异常是当发生某种异常情况时产生的一个信号。用信号通知发生了异常状况即抛出异常。在JavaScript中throw语句就可以抛出异常。捕获异常是指采取相应的手段处理异常信号。try/catch/finally语句则可以捕获异常。
①throw语句
throw语句的语法如下。
throw表达式;
表达式的值是任意类型,可以抛出一个代表错误码的数字,或者包含错误信息的字符串。抛出异常的时候通常采用Error对象,它包含一个name属性表示错误类型,一个message属性存放传递给构造函数的字符串。当抛出异常时,当前正在执行的逻辑将停止,转而执行异常处理程序。
②try/catch/finally语句
try/catch/finally语句用于异常处理,catch和finally从句均为可选,但两者必有其一和try从句组合成语句块。其中try从句定义了需要处理的异常所在的代码块,当try内某次发生异常,调用catch从句内的代码块进行处理。finally从句中放置清理代码,无论异常是否发生,finally的代码都会执行,语法结构如下。
5.函数
函数是由多条语句组成的代码段,用以完成特定任务,只需定义一次,但可能被执行或调用多次。在JavaScript中,函数被视为对象,程序可以为函数设置属性、调用它的方法、将函数赋值给变量、作为参数传递给其他函数。
(1)函数的定义
函数使用function关键字来定义,可以用在函数声明语句或函数表达式中,后跟一组参数以及函数体。函数的基本语法如下。
其中函数名是函数声明语句必需的组成,作用类似变量名,定义的函数对象会赋值给该变量。而对于函数定义表达式的形式,函数名则是可选项。圆括号中包含用逗号隔开的参数名。花括号中包含的是JavaScript语句,这些语句构成了函数体。return语句后跟要返回的值,也是可选项。return语句也可以不带任何返回值。此时函数在停止执行后将返回undefined值。下面的例子给出了通过函数声明和函数定义表达式的方式定义函数。
上述代码通过函数声明语句声明了求和的函数,函数名为sum。
var sum=funct ion(x,y){return x+y;};
上述代码通过函数定义表达式定义了一个求和的函数,并把它赋值给一个变量。此时function关键字后面没有函数名。这是因为在使用函数表达式定义函数时,没有必要使用函数名,通过变量sum即可引用函数。另外,还要注意函数末尾有一个分号,就像声明其他变量时一样。
此外,由于JavaScript的函数属于Function对象,可以使用Function对象的构造函数来创建一个函数,语法如下。
var变量名=new Funct ion([参数1,[参数2,[参数N]]],[函数体]);
其中函数变量名是必选项,表示函数名。参数是可选项。函数体也是可选项,相当于函数体内的程序语句序列,各语句使用分号格开,当忽略此项时函数不执行任何操作。
(2)函数的参数
函数的参数是函数与外界交换数据的接口。外部的数据通过参数传入函数内部进行处理,函数内部的数据也可通过参数传到外界。函数定义时的参数称为形式参数,调用函数时传递的参数称为实际参数。
JavaScript中的函数定义未指定函数形式参数的类型,也不对传入的参数个数进行检查。参数在函数内部是用一个类数组(与数组类似,但并不是数组的实例)的对象arguments来表示的。可以通过arguments对象来访问这个参数数组,获取传入的每一个参数。使用方括号语法访问它的每一个元素(即第1个元素是arguments[0],第2个元素是arguments[1],以此类推),例如,前面定义的求和函数也可以采用下述方式使用参数。
其中arguments[0]的值即为上例x的值,arguments[1]的值等于上例y的值。
此外,可以使用length属性来确定传递进来多少个参数。例如,
(3)函数的调用
函数体中的代码在定义时不会执行,只有该函数被调用时才会执行。下面介绍3种常见的调用函数的方式。
第1种方式是通过普通的函数表达式进行调用。每个函数表达式由一个函数对象和相应的参数列表组成。例如,
var total=sum(1,2)+sum(3,4);
在这种调用中,每个函数的返回值即为调用表达式的值。如果return语句没有值或无return语句,则返回undefined。
第2种方式是在程序中通过“函数名(实参值);”的方式直接调用。如调用sum函数,
sum(2,3);
第3种方式是在事件中调用。当调用事件时,JavaScript可以调用某个事件来响应这个函数。例如,
input type=“but ton“value=“按钮“oncl ick=“sum()“/
(4)函数的作用域
根据函数的作用范围,可以分为公有函数和私有函数。公有函数是指定义在全局作用域中的函数,程序代码均可以调用。而私有函数是指处于局部作用域中的函数,只能被拥有该函数的函数代码调用,外界不能随意调用。通常当函数嵌套定义时,子函数就是父函数的私有函数。
6.对象
对象是JavaScript的一类重要的数据类型,它将很多值(甚至可以包含对象或函数)集合在一起,并通过字符串形式的名字对值进行访问。这些名/值对都是属性,对象也就是属性的无序集合,而对象也可以看成字符串到值的映射。不过严格来说,JavaScript并不是一种面向对象的语言,因为它不具备面向对象语言的一些明显特征,例如它没有类的概念。因此,人们往往把它称为“基于对象”,而不是“面向对象”的语言。
JavaScript的对象主要分3类。
·内置对象:由ECMAScript规范定义的对象或引用类型,如数组Array、函数Function、日期Date和数学Math都是内置对象。
·宿主对象:由JavaScript解释器嵌入的宿主环境(如浏览器)定义的。
·自定义对象:由用户程序创建的对象。
常见的内置对象、宿主对象的使用方法可参考相关书籍。下面仅介绍自定义对象的创建、访问方法。
(1)创建对象
创建对象最基本的方式是通过对象直接量或者执行new操作符。所谓直接量是指直接在程序中出现的常数值。
①通过对象直接量创建对象
对象直接量是由花括号括起来的一组名/值对的集合,其中属性名可以是合法的JavaScript标识符或字符串,值可以是任意类型的表达式,属性名和值由冒号分隔,各名/值对由逗号分隔。例如,
var member={name:“Al ice“,id:123};//会员对象,包括姓名、ID两个属性
var empty={};//空对象,没有属性
②通过new创建对象
new运算符可以创建并初始化一个对象。运算符new后面紧跟一个构造函数,用以初始化一个新创建的对象。例如,
上述代码使用了JavaScript提供的引用类型的内置构造函数如Object()、Array()来创建特定类型的对象。此外,也可以用自定义的构造函数自定义对象的属性和方法。例如,
上述代码中,Member()是自定义的构造函数,函数名首字母大写,以与普通函数区分。要创建Member的新实例,需要使用new运算符调用构造函数。每次调用这个构造函数都会返回一个带3个属性和1个方法的对象。上例中mem1就保存了一个Member的实例。
(2)访问属性
可以通过运算符(.)或方括号([])来获取属性的值。运算符的左侧须是表达式,返回一个对象。运算符(.)的右侧是属性名的标识符,而方括号([])内则是一个结果为字符串的表达式,该字符串即是属性名。例如,
(3)访问方法
在对象中除了使用属性外,有时还需要使用方法。在对象的定义中,this.print Name=function()语句,就是定义对象的方法。对象的方法其实就是定义在对象内部的函数,通过它实现对对象的操作。可以通过运算符(.)调用对象的方法,运算符左侧是对象的表达式,右侧是方法名。例如,
mem1.pr intName;//输出“Al ice“
JavaScript的内置对象介绍请扫二维码。浏览器对象与文档对象介绍请扫二维码。
JavaScript的内置对象
浏览器对象与文档对象