第3章 变量和常量

上一章讲解了数据类型,与数据直接相关的就是变量。变量和常量是每种程序设计语言不可缺少的组成部分。变量和常量都与数据存储相关,变量是程序中其值可以被改变的内存单元。常量也存储于内存中,但其值不可以改变,有的常量作为立即操作数,并不存在于内存中,相关细节超出了本书的范围,在此不做讲述。

● 理解和掌握变量的定义和使用方法

● 理解和掌握常量的特点及其使用方法,简化程序的编码

● 加深对数据类型的理解

以上几点是对读者在学习本章内容时所提出的基本要求,也是本章希望能够达到的目的。读者在学习本章内容时可以将其作为学习的参照。

3.1 常量

程序一次运行活动的始末,有的数据经常发生改变,有的数据从未被改变,也不应该被改变。常量是指从始至终其值不能被改变的数据,JavaScript中的常量类型主要包括字符串常量、数值常量、布尔常量、null和undefined等。常量通常用来表示一些值固定不变的量,比如圆周率、万有引力常量等。

3.1.1 常量分类

在数学和物理学中,存在很多种常量,它们都是一个具体的数值或一个数学表达式。然而在编程语言中基于数据类型的分类,常量包括字符串型、布尔型、数值型和null等,定义形式如下:

        "今天天气真好!";                                 // 字符串常量
        1; e1; 077;                                     // 数值型常量
        true; false;                                    // 布尔型常量

其中,字符串常量的值可以是任意的字符串。布尔型常量只有两种值,即true和false。数值型常量为合法的数值数据,可以使用十进制、八进制和十六进制形式。

3.1.2 使用常量

常量直接在语句中使用,因为它的值不需要改变,所以不需要再次知道其存储地点。下面通过举例演示常量的使用方法。

【范例3-1】练习字符串常量、布尔型常量和数值常量的使用,将八进制、十六进制数输出为十进制数,如示例代码3-1所示。

示例代码3-1

        01  <script language="javascript">                               // 脚本程序开始
        02  <!--
        03       document.write( "<li>JavaScript编程,乐趣无穷!<br>" );    //使用字符串常量
        04       document.write( "<li>" + 3 + "周学通JavaScript!" );      //使用数值常量3
        05       if( true )                                 // 使用布尔型常量true
        06       {
        07           document.write( "<br><li>if语句中使用了布尔常量:" + true );
                                                          // 输出提示
        08       }
        09       document.write( "<li>八进制数值常量011输出为十进制:" + 011 );
                                                          // 使用八进制常量和十进制常量
        10       document.write( "<br><li>十六进制数值常量0xf输出为十进制:" + 0xf );
        11  -->
        12  </script>                                       <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,其结果如图3-1所示。

图3-1 输出各种进制数

【代码解析】该代码段第3行直接在document对象的write方法中使用字符串常量。第4行在document对象的write方法中使用数值常量3,write方法需要输入的是字符串参数,则数字3被隐式转换为字符串“3”。第5行在if语句块中使用布尔型常量true。第9~10行输出时八进制和十六进制数均被转换为十进制后再转换为字符串型。

提示:JavaScript是一门脚本语言,典型的弱类型语言,没有如C++等语言的类型机制,也没有const修饰符将变量定义常量的能力。

3.2 变量

一般情况下,程序运行时的计算结果、用户从外部输入的数据等都需要保存。对于少量的数据,计算机将其保存到系统内存中。为了方便程序代码操作这些数据,编程语言使用变量来引用内存存储单元,通过上一节的学习,读者了解到变量是程序语言最基本的要素,本节将对其进行全面的讲解。

3.2.1 什么是变量

顾名思义,变量是指在程序运行过程中值可以发生改变的量,更为专业的说法就是指可读写的内存单元。可以形象地将其理解为一个个可以装载东西的容器,变量名代表着系统分配给它的内存单元,如图3-2所示。

图3-2 内存单元模型示意图

3.2.2 如何定义变量

JavaScript中,用如下方式定义一个变量。

        var 变量名 = 值;                         // 定义变量
        变量名 = 值;                             // 赋值

var是JavaScript中定义变量的关键字,也可以忽略此关键字。用var关键字声明变量时也可以不赋初始值。

        var 变量名;                             // 定义变量

JavaScript的变量在声明时不需要指定变量的数据类型,程序运行时系统会根据变量的值的类型来确定变量的类型。变量的类型决定了可对变量数据进行的操作,比如在C++中,一个int型变量在X86系列32位CPU上占4个字节。对变量的操作即是针对其所占用的4个字节单元进行,以int方式的访问即一次可访问4个字节单元。此处介绍C++的int类型目的是帮助读者增强对变量数据类型的理解,JavaScript是弱类型语言,不需要过分强调数据类型。

下面分别定义各种类型变量。

● 字符串型

        var str = "JavaScript编程,简单容易!";       // 定义字符串变量

● 布尔型

        var b = true;                              // 定义布尔变量

● 数值型

        var n = 10;                                // 数值型变量

● 复合型

        var obj = new Object();                    // 复合型变量

复合型是指用户自定义类型或JavaScript内置复合类型,比如数组。在应用中复合型的使用非常广泛,本书后面为复合数据类型安排了专门的章节讲解。

变量的使用形式不外乎两种情况,一种是读取其内容,另一种是改写其值。变量的内容一经改写后一直有效,直到再次改写或生命周期结束。

【范例3-2】练习变量的定义和使用。定义一组各种常见类型的变量并输出其值,如示例代码3-2所示。

示例代码3-2

        01  <script language="javascript">         // 脚本程序开始
        02  <!--
        03     var str = "21天学通JavaScript!";    // 定义一个字符串变量
        04     var b = true;                       // 定义一个布尔型变量
        05     var n = 10;                         // 定义一个数值型变量
        06     var m;                              // 声明一个变量m,其类型未知
        07     var o = new Object();               // 定义一个Object类型变量o
        08         p = new Object();                // 定义一个Object类型变量p
        09     document.write( str );              // 分别使用write在当前文档-
        10     document.write( "<br>" );
        11     document.write( b );                // 对象中输出各变量的内容
        12     document.write( "<br>" );           // 输出换行标签
        13     document.write( n );
        14     document.write( "<br>" );           // 输出换行标签
        15     document.write( m );
        16     document.write( "<br>" );           // 输出换行标签
        17     document.write( o );
        18     document.write( "<br>" );           // 输出换行标签
        19     document.write( p );
        20     document.write( "<br>" );           // 改写各变量的值
        21     str = "这是一个字符串";
        22     b = false;
        23     n = 20;
        24     m = 30;                             // 改变变量o的引用,指向一个新建的数组
        25     o = new Array( "data1", "data2" );
        26     document.write( "<font color=red><br>" );
        27     document.write( str );              // 分别使用write在当前文档-
        28     document.write( "<br>" );           // -对象中输出各变量的内容
        29     document.write( b );
        30     document.write( "<br>" );           // 输出换行标签
        31     document.write( n );
        32     document.write( "<br>" );           // 输出换行标签
        33     document.write( m );
        34     document.write( "<br>" );           // 输出换行标签
        35     document.write( "<br>数组o的数据为:" );
        36     document.write( o );
        37     document.write( "<br>数组o的长度为:" + o.length );
        38     document.write( "<br></font>" );
        39     var pp;
        40     document.write( pp );               // 输出未定义变量pp
        41     var pp = 20;
        42  -->
        43  </script>                              <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,结果如图3-3所示。

图3-3 输出变量的类型和值

【代码解析】该代码段演示了各种变量的定义方式。第3~5行定义三个不同类型的变量,定义时就已经赋予初始值,值的类型确定后变量的类型即可确定。第9~20行分别输出各个变量中的值,发现m输出为undefined。与m相关的“不明确”主要包含两方面的含义,一是数据类型不明确,即未确定;其次是变量的值未确定。

第17~19行输出的复合数据类型Object对象的值时仅输出其类型名称。第21~25行改写部分变量的值,第26~40行再次输出所有变量的值,目的在于与前面对照比较。输出数组对象时,将合并其中各元素的值作为整体输出。

提示:因为JavaScript程序的执行是顺序解释执行,所以变量必须先声明才能使用,声明的位置必须在使用变量的语句的前面。

3.2.3 变量的命名

JavaScript变量的命名必须以字母或下画线开始,后可跟下画线或数字,但不能使用特殊符号。以下命名是合法的。

        name                          // 合法的变量名
        _name                         // 合法的变量名
        name10                        // 合法的变量名
        name_10                       // 合法的变量名
        name_n                        // 合法的变量名

以下命名方式是非法的。

        12name                        // 不合法的变量名
        $name                         // 不合法的变量名
        $#name                        // 不合法的变量名

JavaScript对标识符大小写敏感,以下是两个不同的变量名。

        name                          // 变量
        Name                          // 变量

笔者建议为变量取有意义的名称,便于代码的阅读。书写时可用“匈牙利”命名习惯,比如字符串的变量名前加“s”,整型变量名前加“n”,布尔变量名前加“b”等。示例如下:

        var sMyStr = "this is a string";       // 字符串变量
        var nIndex = 0;                        // 数值型变量
        var bStored = true;                    // 布尔型变量

JavaScript内置对象的方法命名规律为第一个单词全小写,后面每个单词首字母大写。示例如下:

        isNaN                                  // 规范的命名
        cookieEnabled                          // 规范的命名

【范例3-3】定义两个数字变量,分别赋予10,20初始值。输出两个变量的值,再交换两个变量的值后输出,熟悉匈牙利命名规范,如示例代码3-3所示。

示例代码3-3

        01  <script language="javascript">                  // 脚本程序开始
        02  <!--
        03       var nA = 10;                               // 定义两变量并赋初始值
        04       var nB = 20;
        05       document.write( "交换前<br> " );            // 输出交换前两变量的值
        06       document.write( "<li>nA = " + nA );        // 输出nA
        07       document.write( "<li>nB = " + nB );        // 输出nB
        08       var nTemp = nA;                            // 交换两变量的值
        09       nA = nB;
        10       nB = nTemp;
        11       document.write( "<br>交换后<br> " );        // 输出交换后两变量的值
        12       document.write( "<li>nA = " + nA );        // 输出nA
        13       document.write( "<li>nB = " + nB );        // 输出nB
        14  -->
        15  </script>                                       <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,其结果如图3-4所示。

图3-4 交换前后的变量值

【代码解析】第3、4行定义两变量并赋值,第6、7行分别输出变换前的变量内容。第8~10行定义一个“临时”变量参与交换nA和nB的值。第12、13行输出nA和nB。

提示:良好的书写习惯可大大减少代码后期维护的工作量。“匈牙利”命名法不是硬性规范,原为微软的一个优秀程序员所创,但良好的习惯值得学习和效仿。

3.2.4 变量的作用范围

作用域是指有效范围,JavaScript变量的作用域有全局和局部之分。全局作用域的变量在整个程序范围都有效,局部作用域指作用范围仅限于变量所在的函数体。JavaScript不像其他语言那样有块级作用域。变量同名时局部作用域优先于全局作用域。

【范例3-4】编写程序,测试变量的作用范围的优先级,如示例代码3-4所示。

示例代码3-4

        01  <script language="javascript">                      // 脚本程序开始
        02  <!--
        03       var nA = 10;                                    // 定义全局变量nA
        04       function func()
        05       {
        06          var nA = 20;                                 // 定义局部变量nA并输出
        07          document.write( "<li>局部作用范围的nA:" + nA );
                                                                // 输出nA
        08       }
        09       func();                                         // 调用函数func
        10       document.write( "<li>全局作用范围的nA:" + nA );  // 输出全局nA
        11  -->
        12  </script>                                           <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,其结果如图3-5所示。

【代码解析】第3行定义的变量nA,其有全局作用域。第4~8行定义一个函数,其内定义一个变量nA,与全局变量nA同名。第9行调用函数func,以输出局部变量nA。第10行输出全局变量nA,目的与func输出的局部变量作比较。

图3-5 输出同名变量

注意:当局部变量与全局变量同名时,局部变量要使用var关键字。

3.2.5 变量的用途

变量主要用于存储数据,比如计算的结果、存储用户输入的数据等。一部分变量作为对象的引用,通过变量来操作对象的内容或调用对象的方法,下面举例说明。

【范例3-5】创建一个数组,其内容包含站点用户中不同类型角色的名称,如示例代码3-5所示。

示例代码3-5

        01  <script language="javascript">             // 脚本程序开始
        02  <!--
        03       var actorAry = new Array( "超级管理员", "管理员", "VIP 用户", "普通用户" );
                                                      // 角色数组
        04       document.write("用户角色:");            // 标题
        05       for( n in actorAry )                   // 遍历数组
        06       {
        07           document.write( "<li>" + actorAry[n] );
                                                      // 通过变量actorAry操作角色数组
        08       }
        09  -->
        10  </script>                                  <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,其结果如图3-6所示。

图3-6 输出数组元素

【代码解析】第3行定义变量actorAry,其引用新建的数组。第5~8行输出数组各元素。变量actorAry将代表一个数组对象,直到其被赋予新的值。通过actorAry可以操作其代表的数组的数据或调用数组的方法。

3.3 JavaScript关键字详解

关键字为系统内部保留的标识符,其用途特殊,用户的标识符不能与关键字相同。下面列出JavaScript中常见关键字,如表3-1所示,可供读者参照。

表3-1 JavaScript常见关键字

注意:上表列出了常用的关键字,其中大部分内容读者现在不必知道,以后用到相关内容时将再做讲解。

3.4 小结

本章内容让读者了解了什么是常量和变量,以及它们如何使用,常量最终可以理解为一些程序运行的始末不能改变的量。变量则是那些值可以发生改变的量,主要用于保存计算的中间结果或其他数据。变量的另一个重要的用途是引用各种各样的对象,通过变量可以操作内存中的对象。

变量的命名有一定的规范,重要的一点是不能与系统保留的关键字同名。规范的命名不仅使代码工整漂亮,而且能降低后期维护工作的难度。下一章将讲解另一个重要的内容,表达式与运算符。如果读者对本章内容还有什么疑问,可以参考《完全手册:HTML+CSS+JavaScript实用详解》(电子工业出版社,叶青)和《JavaScript权威指南》(机械工业出版社)等书籍。

3.5 习题

一、常见面试题

1.简单说明一下JavaScript中常量和变量的定义及区别。

【解析】本题考查的是变量和常量的定义。

【参考答案】常量通常用来表示一些值固定不变的量,比如圆周率、万有引力等,一般直接使用,不需要使用关键字定义,包括字符串型、布尔型、数值型和null等。变量是指在程序运行过程中值可以发生改变的量,更为专业的说法就是指可读写的内存单元。一般使用var来定义变量。

2.简述变量的作用范围。

【解析】任何语言的变量都是有一定时效性的,不是一直有效,也不是一直存在。本题考核的是对变量作用域的了解。

【参考答案】JavaScript变量的作用域有全局和局部之分。全局作用域的变量在整个程序范围都有效,局部作用域指作用范围仅限于变量所在的函数体。

二、简答题

1.什么是变量?它和常量有什么区别?

2.变量的作用有哪些?JavaScript中变量的类型有哪些?

3.写出JavaScript中的运算符关键字。

三、综合练习

1.编写一个程序,将数字13、55、37、33、45、9、60、21、10从小到大排序,并将排序后的各数字输出。

【提示】定义一个数组变量,将各数字填入数组。遍历数组,如果第n个元素小于第n-1个,则交换两者的内容,如此循环操作即可,参考代码如下:

        01  <script language="javascript">
        02       <!--
        03       var oMyArray = new Array( 13, 55, 37, 33, 45, 9, 60, 21, 10 );
                                                          // 定义变量引用一个数组对象
        04       document.write( "排序前:" + oMyArray );     // 输出排序前的数组
        05       for ( index in oMyArray )                  // 开始排序
        06       {
        07          for ( i in oMyArray )                   // 两两比较
        08          {
        09             if( oMyArray[index]<oMyArray[i] )    // 如果当前元素小于第i个元素
        10             {
        11                nTemp = oMyArray[index];          // 交换位置
        12                oMyArray[index] = oMyArray[i];
        13                oMyArray[i] = nTemp;
        14             }
        15          }
        16       }
        17           document.write( "<br>排序后:" + oMyArray );
                                      // 输出排序后的数组
        18  -->
        19  </script>                 <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,其结果如图3-7所示。

图3-7 数组排序

2.实现一个求圆面积的程序,半径由用户从外部输入,计算结果输出到当前页面中。

【提示】根据圆面积公式S=π*r2可计算出面积。使用window对象的prompt方法实现半径的输入。调用Math对象的PI常作为圆周率π,输出使用document对象的write方法,参考代码如下:

        01  <script language="javascript">                      // 脚本程序开始
        02  <!--
        03       var r = prompt( "请输入圆的半径:", "0" );        // 用户输入圆半径
        04       if( r != null )                                 // 判断输入的合法性
        05       {
        06           var square = parseFloat( r )*parseFloat( r )*Math.PI;
                                                                // 计面积 s=π*r*r
        07           document.write("半径为" + parseFloat( r ) + "的圆面积为:" + square );
                                                                // 在页面中输出结果
        08       }
        09       else                                            // 输入不合法
        10       {
        11           alert("输入不合法!");                       // 输出提示信息
        12       }
        13  -->
        14  </script>                                           <!--脚本程序结束-->

【运行结果】打开网页文件运行程序,其结果如图3-8、图3-9所示。

图3-8 输入圆半径

图3-9 输出圆面积

四、编程题

1.编写程序比较三个数的大小,并依次输出。

【提示】可以定义三个变量,然后按照两两比较的办法进行。

2.找出5个数中最大的一个数,并输出。

【提示】可以定义5个变量,然后将第1个数值与后面的数值进行比较,得出最大者,再用第2个数依次比较,依此类推,最终得到结果。