2.2 ECMAScript变量
本节介绍关于ECMAScript变量的知识,从本节开始就接触到ECMAScript语法的核心部分内容。
2.2.1 ECMAScript变量是弱类型的
在学习高级编程语言的过程中,最先接触的,也是最重要的概念应该就是变量了。所谓“变量”,一般意义上理解就是程序中用于存储数据信息的容器,或者也可以理解为用于替代数据信息的符号。
ECMAScript规范中定义的变量既可以存储数据信息,也可以定义为替代表达式的符号。一般都是通过“var”关键字来定义变量,且定义的均是无特定类型的变量(也称为弱类型)。因此,ECMAScript变量可以初始化为任意类型的值,且可以随时改变变量的数据类型。当然,我们不建议随意改变变量的数据类型,建议初始化成什么类型就一直沿用该类型,避免不必要的麻烦。
2.2.2 变量的声明
ECMAScript规范中规定通过“var”(单词variable的缩写)关键字来定义声明的变量,当然也可以不使用“var”关键字。一般使用“var”关键字定义的是局部变量,而不使用“var”关键字定义的是全局变量。
此外,在ECMAScript规范中还规定一些定义变量的准则,具体描述如下:
- ECMAScript变量需要以字母开头、大小写字母均可、且对大小写字母敏感(例如:a和A是不同的变量);
- ECMAScript变量也可以用“$”或“_”符号开头;
- ECMAScript变量分为全局变量和局部变量,且二者的定义方式、作用域及使用用法有明显区别。
下面,来看一个声明ECMAScript变量的代码示例(详见源代码ch02目录中ch02-js-variable.html文件)。
【代码2-1】
01 <script type="text/javascript"> 02 var i = 1; 03 var j = 2; 04 var s = i + j; 05 console.log("s = " + s); 06 </script>
关于【代码2-1】的分析如下:
第02~03行代码通过“var”关键字分别定义了两个变量(i和j),并进行了初始化赋值操作。注意,这里赋的值均是整数类型,因为ECMAScript变量弱类型的特点,所以解释程序会自动为变量创建整数值;
第04行代码通过“var”关键字定义了一个变量表达式(var s = i + j;),而表达式中的变量“i”和“j”正是第02~03行代码中定义的,表达式运算的结果则会保存在变量“s”中;
第05行代码通过console.log()函数向浏览器控制台输出调试信息(表达式变量“s”的运算结果)。
运行测试【代码2-1】所指定的HTML页面,并使用浏览器控制台查看调试信息,页面效果如图2.1所示。在浏览器控制台中输出了【代码2-1】中第05行JS代码所定义的调试信息。
图2.1 ECMAScript变量声明
2.2.3 改变变量数据类型
我们在前文中介绍了ECMAScript变量弱类型的特点,因此ECMAScript规范允许改变ECMAScript变量的数据类型。简单来说,就是初始化一个ECMAScript变量时为一种数据类型,后面还可以改变该变量的数据类型。这对于使用强类型变量的C语言的用户和Java语言来说,是有点不可思议的,不过这也恰恰体现了JavaScript脚本语言的灵活性。
下面来看一个改变ECMAScript变量数据类型的代码示例(详见源代码ch02目录中ch02-js-variable-revise.html文件)。
【代码2-2】
01 <script type="text/javascript"> 02 var i = 1, s = "EcmaScript"; 03 console.log("i : " + i); 04 console.log("s : " + s); 05 i = s; 06 s = 1; 07 console.log("i = " + i); 08 console.log("s = " + s); 09 </script>
关于【代码2-2】的分析如下:
第02行代码通过“var”关键字在一行内分别定义了两个变量(i和s),并进行了初始化赋值操作。注意,ECMAScript语法规定可以在一行内定义多个变量,并允许初始化操作,数据类型也可以不同;
第03~04行代码分别通过console.log()函数向浏览器控制台输出调试信息(变量初始化的数据内容);
第05行代码通过表达式将变量“s”的数据内容赋给了变量“i”。注意这里的数据类型是不一致的,如果是变量强类型的编程语言(C语言和Java语言),肯定会报错了。但是,ECMAScript语法规范却是允许的,读者看后面的调试结果就知道了。
第07~08行代码再次分别通过console.log()函数向浏览器控制台输出调试信息(变量改变后的数据内容)。
运行测试【代码2-2】所指定的HTML页面,并使用浏览器控制台查看调试信息,页面效果如图2.2所示。在浏览器控制台中分别输出了【代码2-2】中第03~04行与第07~08行JS代码所定义的调试信息,改变了数据类型的变量内容也被成功输出了。
图2.2 改变ECMAScript变量数据类型
2.2.4 变量命名习惯
计算机软件编程有许多关于变量命名的习惯,比较著名的有Camel标记法(小写字母开头)、Pascal标记法(大写字母开头)和匈牙利类型标记法(个人认为集合了前两者的优点)。
匈牙利类型标记法是为了纪念具有传奇色彩的匈牙利籍微软程序员(Charles Simonyi)而命名的,自然该标记法也是Charles Simonyi首先提出的。关于Charles Simonyi其人,用“伟大”来形容其功绩是一点也不为过的(自己搜索一下吧)。
那么匈牙利类型标记法是如何定义呢?简单来讲,就是变量名由该变量所代表数据类型的小写字母缩写开始,后面由该变量代表的具体含义的单词(首字母大写,可为缩写)组成。同时,匈牙利类型标记法约定了代表数据类型的小写字母缩写,关于ECMAScript语法约定的匈牙利类型标记法见表2-1。
表2-1 匈牙利类型标记法(ECMAScript)
匈牙利类型标记法在使用上是非常灵活的,读者领会到其中的精要即可,需要掌握的是其总体原则,可以不必拘泥不变。
2.2.5 未声明的变量
ECMAScript规范中对于变量的声明还有一点比较特殊的规定,那就是可以不通过“var”关键字来声明变量,这一点与其他大多数程序语言是有所区别的。当然,前面也提到对于未使用“var”关键字声明的变量一般都是全局变量,关于全局变量与局部变量的内容会在后面专门进行具体的介绍。
下面来看一个未使用“var”关键字声明ECMAScript变量的代码示例(详见源代码ch02目录中ch02-js-variable-novar.html文件)。
【代码2-3】
01 <script type="text/javascript"> 02 var sVar = "EcmaScript Variable"; 03 console.log("sVar : " + sVar); 04 sNoVar = sVar + "with no var"; 05 console.log("sNoVar : " + sNoVar); 06 </script>
关于【代码2-3】的分析如下:
第02~03行代码通过“var”关键字分别定义一个变量(sVar),并进行了初始化赋值操作,然后在浏览器控制台窗口中输出了该变量的内容;
第04~05行代码未通过“var”关键字定义一个变量(sNoVar),并通过变量(sVar)连接字符串的方式对其进行初始化赋值操作,然后在浏览器控制台窗口中输出该变量的内容。
运行测试【代码2-3】所指定的HTML页面,并使用浏览器控制台查看调试信息,页面效果如图2.3所示。【代码2-3】中第04行脚本代码没有使用“var”关键字定义的变量(sNoVar)的内容成功显示出来了,这说明第04行代码的初始化赋值操作是有效的,JavaScript解释器是能够识别变量(sNoVar)的。
图2.3 未声明的ECMAScript变量
提示
虽然ECMAScript语法不强制使用“var”关键字定义变量,这给编程设计带来了灵活性,但同样也会带来危险性。如果对于未声明的变量失去监管(特别是代码体量很大的场景),会带来意想不到的严重后果。因此,建议设计人员还是保持良好的编程习惯,按照规范严格声明所有的变量。
2.2.6 严格模式(use strict)
在ECMAScript规范中,虽然允许可以不通过“var”关键字来声明变量,但这一点终归是不被大多数严谨的设计人员所接受的。不仅仅是因为这类代码的可读性与可维护性比较差,最主要的是因为如果不通过“var”关键字来声明变量,在大型Web开发项目中会出现很多意想不到的错误,大大增加调试纠错的难度。
因此,在ECMAScript 5规范之后,增加了一个严格模式“use strict”字面量用来强制设计人员通过“var”关键字来声明变量,否则调试运行时就会报错。另外,“use strict”字面量必须放置在所有JavaScript脚本代码的最顶端,如果是仅仅针对一个函数内的代码,就要放置在函数体内代码的最开始位置。
下面来看一个使用严格模式(use strict)的JavaScript代码示例(详见源代码ch02目录中ch02-js-variable-use-strict.html文件),这段代码是在【代码2-3】的基础上修改而完成的。
【代码2-4】
01 <script type="text/javascript"> 02 "use strict"; 03 var sVar = "EcmaScript Variable"; 04 console.log("sVar : " + sVar); 05 sNoVar = sVar + "with no var"; 06 console.log("sNoVar : " + sNoVar); 07 </script>
关于【代码2-4】的分析如下。
代码【代码2-4】与【代码2-3】的唯一区别就是在第02行代码(JavaScript脚本代码的最顶端)定义了“use strict”字面量;
运行测试【代码2-4】所指定的HTML页面,并使用浏览器控制台查看调试信息,页面效果如图2.4所示。从浏览器控制台中输出的结果来看,【代码2-4】中第05行代码没有使用“var”关键字定义变量(sNoVar),被浏览器报错了(undeclared variable,未声明的变量)。这个结果与【代码2-3】运行结果是完全不同的(见图2-3)。
图2.4 ECMAScript严格模式(use strict)
严格模式(use strict)对于编写JavaScript脚本代码来说非常有实际作用,可以有效地避免未声明变量。其实,对于严谨的设计人员来讲,使用变量前必须先声明该变量,这是一个良好的习惯,建议读者从一开始就养成良好的编程习惯。