2.6 变量
变量(variable)是相对常量而言的,常量通常是一个不会改变的固定值,而变量是对应到某个值的一个符号,这个符号中的值可能会随着程序的执行而改变,因此称为“变量”。在很多情况下,变量又称为标识符(identifier)。
2.6.1 变量的命名方式
变量可以用来存储数据,JavaScript是通过变量名来调用这些被存储的数据。变量名必须以ASCII字符或下划线(_)开头,第1个字母不能是数字,但其后可以是数字或其他字母。以下代码中的变量名都是合法的变量名:
x X _x x_1
注意
JavaScript对大小写是敏感的,因此,变量x与变量X是两个不同的变量。
虽然变量名只要不是以数字开头即可,但是对于变量名有个不成文的命名约定,这个约定与Java的命令约定相同:
■从变量名上应该可以看出变量的作用。例如要设置一个代表当天日期的变量,将变量名设为“date”,要比设为“abc”要更易于理解。
■如果变量名是一个单独的单词,如“date”,那么该变量名应该全部使用小写;如果变量名由两个或多个单词组成,那么从第二个单词开始,后面的所有单词的首字母都必须大写,如“theDate”“otherDate”等。
■变量名不能与JavaScript中的保留字相同。
注意
以上命名约定只是一个“约定”而已,除了不能与保留字相同之外,其余两点约定可以遵守,也可以不遵守。
2.6.2 变量类型
JavaScript与其他程序语言有些区别,其他程序语言大多需要为变量指定一个数据类型,例如将一个变量指定为整数型,那么这个变量就只能存储整数型数据,不可以存储浮点型或其他类型的数据。而JavaScript中的变量是没有类型(notype)的,这就意味着在JavaScript中的变量可以是任何一种数据类型。例如先将一个数字型数据赋给一个变量,在程序运行过程中,再将一个布尔型数据赋给同一个变量,这在JavaScript中是合法的。如以下代码:
x = "abc"; x = 101;
2.6.3 定义变量
在JavaScript中,使用一个变量之前,必须先定义该变量。只有在定义了一个变量之后,系统才会准备一个内存空间来存储这个变量的值,而程序员可以通过变量名来存储或读取变量的值。在JavaScript中可以使用关键字var来定义一个变量。如以下代码:
var x; var X; var _x; var x_1;
一个var关键字也可以同时定义多个变量,变量之间用逗号隔开,如以下代码:
var x,X,_x,x_1;
在定义了变量之后,如果没有为变量赋值,那么该变量的初始值为undefined。JavaScript支持在定义变量的同时为变量指定初始值,请看以下代码:
var x = "abc"; var n = null; var bFlag = true; var theDate = "2007-6-20" , i =100;
注意
变量一旦被定义之后,是不能再被删除的。
2.6.4 定义变量的注意事项
虽然在JavaScript中定义变量是一件十分简单的事情,但是在定义变量时,有以下几点是需要注意的。
1. 重复定义变量
【实例2.4】在JavaScript中可以重复定义变量,并且不会产生任何错误,请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>重复定义变量</title> 04 <script type="text/javascript"> 05 <!-- 06 var x = 1; 07 document.write(x+"<br>"); 08 var x = "test"; 09 document.write(x); 10 --> 11 </script> 12 </head> 13 <body> 14 </body> 15 </html>
【代码说明】代码第6行和第8行定义的是x变量,但第6行定义的是数字数据,而第8行定义的是字符串数据。在JavaScript中,var表示任意类型,或者说无类型,也就是变量的类型要根据其值来判断。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample04.htm”里的内容,其运行结果如图2.4所示。在本例中变量x被定义了两次,并且每次定义时都赋予了不同类型的初始值。在执行该文件时,是不会出现任何错误的。
2. 变量必须先定义后使用
【实例2.5】在JavaScript中的变量必须先定义后使用,没有定义过的变量不能直接使用。请看以下代码,注意加粗的文字。
01 <html>
02 <head>
03 <title>未定义变量</title>
04 <script type=" text/javascript">
05 <!--
06 document.write(x);
07 -->
08 </script>
09 </head>
10 <body>
11 </body>
12 </html>
【代码说明】代码第6行直接输出了一个x变量,但在代码第1~5行中并没有这个变量的定义。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample05.htm”里的内容。在本例中,没有定义变量x,但是却使用document.write()方法来输出x的值,因此会产生错误,其错误信息如图2.5所示。
3. 给未定义的变量赋值
【实例2.6】虽然JavaScript不能读取未定义的变量,但是JavaScript却可以给一个未定义的变量赋值。此时JavaScript会隐式定义该变量。请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>给未定义的变量赋值</title> 04 <script type="text/javascript"> 05 <!-- 06 x = "给未定义的变量赋值"; 07 document.write(x); 08 --> 09 </script> 10 </head> 11 <body> 12 </body> 13 </html>
【代码说明】代码第6行定义了x变量,但没有使用var关键字,代码第7行依然可以输出这个变量的值。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample06.htm”里的内容。在本例中,虽然没有使用var关键字定义x变量,但是却可以直接给x变量赋值。其运行结果如图2.6所示。
注意
隐式定义的变量默认为全局变量。有关全局变量的概念将在后续章节里介绍。
4. 引用未赋值的变量
【实例2.7】已经定义但未赋值的变量可以引用,此时的变量值为undefined。请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>给未定义的变量赋值</title> 04 <script type="text/javascript"> 05 <!-- 06 var x; 07 document.write(x); 08 --> 09 </script> 10 </head> 11 <body> 12 </body> 13 </html>
【代码说明】代码第6行定义了x变量,但并没有为其赋值,那代码第7行是否可以直接输出变量x的值呢?答案是肯定的,输出结果为undefined。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample07.htm”里的内容。在本例中,虽然定义了变量x,但是并没有为变量x赋值。因此,在输出变量x的值时,显示为undefined。其运行结果如图2.7所示。
2.6.5 变量的值
由于JavaScript的变量不需要指定数据类型,因此变量值可以是任何类型的数据,包括如下内容。
■数字型(number):整数型或浮点数,如123或12.3。
■布尔型:又称逻辑型(logical),只能是true或false。
■字符串型(string):用单引号或双引号括起来的字符串。
■空值(null):这是一种特殊的类型,表示没有值,即该变量为空。
■未定义值(undefined):表示变量还没有被赋值。
2.6.6 变量的有效范围
变量可以根据其有效范围分为全局变量与局部变量两种。其中全局(global)变量从定义开始,到整个JavaScript代码结束为止,都可以使用;而局部(local)变量只在函数内部生效。
【实例2.8】有关全局变量的使用方法,请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>全局变量</title> 04 <script type="text/javascript"> 05 <!-- 06 //定义全局变量x 07 var x = "这是一个全局变量"; 08 //定义函数 09 function linkClick() 10 { 11 //在函数体里使用全局变量 12 alert(x); 13 } 14 --> 15 </script> 16 </head> 17 <body> 18 <!--单击超链接时调用函数--> 19 <a href="javascript:linkClick()">请点击</a> 20 <script type="text/javascript"> 21 <!-- 22 //输出全局变量 23 document.write(x); 24 --> 25 </script> 26 </body> 27 </html>
【代码分析】本例代码中的关键点如下所示:
(1)定义了一个全局变量x,并为x赋值。
(2)定义了一个名为linkClick的函数,虽然在该函数里没有定义变量x,但是变量x也能在该函数里直接使用,因为这是一个全局变量。
(3)在网页的正文里创建了一个超链接,单击该超链接将会执行linkClick()函数,弹出一个警告框,警告框里的内容为全局变量x的值。
(4)在网页正文的最后,增加了另一个JavaScript代码块,该代码块的作用是输出全局变量x的值。虽然该代码块与<head>标签中的JavaScript代码块是分离的,但也可以直接使用上面代码块里定义的全局变量x。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample08.htm”里的内容,其运行结果如图2.8所示。
【实例2.9】有关局部变量的使用方法请看以下代码,注意加粗的文字:
01 <html> 02 <head> 03 <title>局部变量</title> 04 <script type="text/javascript"> 05 <!-- 06 //定义函数 07 function linkClick() 08 { 09 //在函数体里使用局部变量 10 var x = "这是一个局部变量"; 11 alert(x); 12 } 13 --> 14 </script> 15 </head> 16 <body> 17 <!--单击超链接时调用函数--> 18 <a href="javascript:linkClick()">请点击</a> 19 </body> 20 </html>
【代码分析】代码第7~12行使用function关键字定义了一个函数,其中第10行定义了x变量,方法内定义的变量称为局部变量。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample09.htm”里的内容,其运行结果如图2.9所示。在本例中,linkClick()函数中的变量x为局部变量。
2.6.7 使用变量的注意事项
在使用变量的时候,需要注意以下几点。
1. 变量的优先级
【实例2.10】如果在函数体里定义了一个名称与全局变量名相同的局部变量,那么在该函数体里全局变量将不起作用,这就相当于全局变量并不存在。请看以下代码,注意加粗的文字。
01 <html> 02 <head> 03 <title>局部变量的优先级比同名的全局变量要高</title> 04 <script type="text/javascript"> 05 <!-- 06 //定义全局变量 07 var x = "这是一个全局变量" 08 //定义函数 09 function writeText() 10 { 11 //定义了一个与全局变量同名的局部变量 12 var x = "这是一个局部变量"; 13 //输出局部变量 14 document.write(x+"<br>"); 15 } 16 //调用函数 17 writeText(); 18 //输出全局变量 19 document.write(x+"<br>"); 20 --> 21 </script> 22 </head> 23 <body> 24 </body> 25 </html>
【代码说明】本例代码中的关键点如下所示:
(1)代码第7行定义了一个名为“x”的变量,并为x赋值。该变量为全局变量。
(2)第9~15行定义了一个函数,在该函数里同样定义了一个名为“x”的局部变量,并为该变量赋上另一个值。
(3)第17行调用函数,此时输出变量x的值为局部变量的值。
(4)第19行输出变量x的值,此时x的值为全局变量的值。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample10.htm”里的内容,其运行结果如图2.10所示。
提示
如果局部变量与全局变量的名称一样,就好像在函数体内定义了另一个变量,全局变量在该函数体内并不起到任何作用。
2. 在函数体内定义全局变量
【实例2.11】在函数体内使用var关键字定义的变量为局部变量,如果要在函数体内定义全局变量,则不能使用var关键字,只需要直接给变量赋值即可。请看以下代码,注意加粗的文字:
01 <html> 02 <head> 03 <title>在函数体内定义全局变量</title> 04 <script type="text/javascript"> 05 <!-- 06 //定义函数 07 function writeText() 08 { 09 //使用var关键字定义的变量为局部变量 10 var x = "这是一个局部变量"; 11 //直接给没有定义的变量赋值,该变量即为全局变量 12 y = "这是一个全局变量"; 13 //在函数体内可以输出局部变量 14 document.write(x+"<br>"); 15 //在函数体内也可以输出全局变量 16 document.write(y+"<br>"); 17 } 18 //调用函数 19 writeText(); 20 //在函数体外可以输出全局变量,但不能输出函数体内的局部变量 21 document.write(y+"<br>"); 22 //如果有以下代码,将会出错 23 //document.write(x+"<br>"); 24 --> 25 </script> 26 </head> 27 <body> 28 </body> 29 </html>
【代码说明】本例代码中的关键点如下所示:
(1)代码第7~17行定义了一个函数。
(2)第10行在函数体内里使用var关键字定义了一个名为“x”的变量,该变量为局部变量,只能在该函数体中使用。
(3)第12行在函数体内直接为变量y赋值,该变量为全局变量。
(4)第21行在函数体外输出全局变量的值。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample11.htm”里的内容,其运行结果如图2.11所示。
注意
(1)在本例中,如果在函数体外输出变量x的值,将会产生错误。
(2)全局变量最好在函数体外定义,所以在函数体内定义局部变量时,最好都加上var关键字。
3. 嵌套函数体中的变量的有效范围
【实例2.12】JavaScript中的函数是可以嵌套的,每个嵌套函数中的变量都可以在该函数体内,以及嵌套的函数体内起作用,但不能在父级或父级以上的函数体内起作用。请看以下代码,注意加粗的文字:
01 <html> 02 <head> 03 <title>嵌套函数中的变量</title> 04 <script type="text/javascript"> 05 <!-- 06 //定义函数 07 function writeText() 08 { 09 //此处定义的局部变量可以在整个writeText()函数体中使用 10 //也可以在嵌套在该函数体中的其他函数中使用 11 var x = "这是一个局部变量"; 12 //定义一个嵌套的函数 13 function writeText1() 14 { 15 //嵌套函数中的变量,该变量只能在writeText1()函数体中使用 16 //不能在writeText1()函数体之外使用 17 var y = "这是一个嵌套函数中的变量"; 18 //输出局部变量x 19 document.write(x+"<br>"); 20 //输出嵌套函数中的变量y 21 document.write(y+"<br>"); 22 } 23 //调用嵌套的函数 24 writeText1(); 25 //输出局部变量x 26 document.write(x+"<br>"); 27 //如果有以下代码,将会出错 28 //document.write(y+"<br>"); 29 } 30 //调用函数 31 writeText(); 32 --> 33 </script> 34 </head> 35 <body> 36 </body> 37 </html>
【代码说明】本例代码中的关键点如下所示:
(1)代码第7~29行定义了一个名为“writeText”的函数。
(2)代码第11行在writeText()函数中定义了一个名为“x”的变量,该变量可以在整个writeText()函数中使用,包括嵌套在该函数中的函数里。
(3)代码第13~22行在writeText()函数中嵌套了一个名为“writeText1”的函数。
(4)代码第17行在writeText1()函数中定义了一个名为“y”的变量,该变量可以在整个writeText1()函数中使用,但不能在writeText()函数中使用。
(5)第19~21行在writeText1()函数中可以输出变量x与变量y的值。
(6)第26~28行在writeText()函数中只可以输出变量x的值,不能输出变量y的值。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample12.htm”里的内容,其运行结果如图2.12所示。
4. 局部变量在整个函数体内都有效
JavaScript中局部变量的有效范围与其他语言中局部变量的有效范围不同,JavaScript中,只要在函数体内定义了局部变量,该局部变量就会在整个函数体内有效,而不是从定义局部变量的那行代码开始起效。
【实例2.13】请看以下代码,注意加粗的文字:
01 <html> 02 <head> 03 <title>局部变量在整个函数体内都有效</title> 04 <script type="text/javascript"> 05 <!-- 06 //定义一个全局变量 07 var x = "这是一个全局变量"; 08 //定义函数 09 function writeText() 10 { 11 //输出变量x的值 12 document.write(x+"<br>"); 13 //定义一个与全局变量同名的局部变量 14 var x = "这是一个局部变量"; 15 //输出局部变量x 16 document.write(x+"<br>"); 17 } 18 //调用函数 19 writeText(); 20 --> 21 </script> 22 </head> 23 <body> 24 </body> 25 </html>
【代码说明】本例代码中的关键点如下所示:
(1)代码第7行定义了一个名为“x”的全局变量,并为该变量赋值。
(2)代码第9~17行定义一个函数,在该函数中第一个语句就是输出变量x的值。因为在该函数中还没有定义名为“x”的局部变量,从理论上而言,此时变量x应该还是全局变量x,其值应该是“这是一个全局变量”,可是事实上,变量x此时的值为“undefined”,如图2.13所示。
(3)造成变量x的值为“undefined”的原因是,在函数体内定义了名为“x”的局部变量,在JavaScript中,无论在哪里定义了局部变量,都会在整个函数体内起效,因此函数体中的代码等同于以下代码:
var x; document.write(x+"<br>"); x = "这是一个局部变量"; document.write(x+"<br>");
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample13.htm”里的内容,其运行结果如图2.13所示。
【实例2.14】JavaScript的这种局部变量在整个函数中都有效的情况还体现在不区分程序块上。请看以下代码,注意加粗的文字:
01 <html> 02 <head> 03 <title>局部变量在整个函数体内都有效</title> 04 <script type="text/javascript"> 05 <!-- 06 function writeText() 07 { 08 //创建一个循环语句 09 for (var j=0;j<10;j++) 10 { 11 //在循环语句中定义一个变量k 12 //该变量不但在循环语句中起作用,还会在整个函数体中起作用 13 var k = 20; 14 document.write("j = "+j+"<br>"); 15 } 16 //变量k可以在循环语句之外起作用 17 document.write("k = "+k+"<br>"); 18 //变量j也同样可以在循环语句之外起作用 19 document.write("j = "+j+"<br>"); 20 } 21 //调用函数 22 writeText(); 23 --> 24 </script> 25 </head> 26 <body> 27 </body> 28 </html>
【代码说明】本例代码中的关键点如下所示:
(1)代码第6~20行定义了一个函数,并在该函数中创建了一个for循环语句。
(2)在循环语句中定义了两个变量,一个是用来控制循环的变量j,另一个是局部变量k。
(3)第14行在循环语句中可以循环输出变量j的值。
(4)第17~19行在循环语句外也可以输出变量j和k的值。这一点在其他语言中是不允许的。
【运行效果】以上代码为本书配套代码文件目录“代码\第02章\sample14.htm”里的内容,其运行结果如图2.14所示。
提示
为了让JavaScript程序更易于理解,最好在函数的开头先定义局部变量。