<script language="javascript"> //following section is used to initialize golbal variables (good) var valueA = 0; //initialize valueA to be sero (bad) var valueB = 1; ... //call f1 function after waiting for 50 seconds. (good) setTimeout(f1,50000); //set timeout to be 20s (copy error) ... </script>
这样的注释方式在 JavaScript 代码中经常见到。"initialize valueA to be sero" 这样的注释有什么用呢?难道阅读程序的工程师从"var valueA = 0;"复制语句中看不出来么?"set timeout to be 20s"这条注释,不只是因拷贝、粘贴引起的时间大小的错误,同时也误导了程序员对这条语句的理解。setTimeout() 函数的作用并非是设置函数执行的超时时间,而是等待一定时间后执行所调用的函数,害人匪浅呀。这样的注释内容宁可删掉。
此外,JavaScript 的注释有两种"//" 和"/* .... */",建议"//"用作代码行注释,"/* .... */"形式用作对整个代码段的注销,或较正式的声明中,如函数参数、功能、文件功能等的描述中。
标识符命名
JavaScript 中的标识符的命名规则:
以字母、下划线'_'或美元符号'$'开头
允许名称中包含字母,数字,下划线'_'和美元符号'$'
区分大小写
变量、参数、成员变量、函数等名称均以小写字母开头,构造器的名称以大写字母开头。下划线'_'开头的变量一般习惯于标识私有 / 局部成员。而美元符号'$'开头的变量习惯于标识系统相关,比如系统进程等。应避免用下划线'_'或美元符号'$'来命名标识符。尽可能地降低代码的阅读负担。
声明
变量的声明
尽管 JavaScript 语言并不要求在变量使用前先对变量进行声明。但我们还是应该养成这个好习惯。这样可以比较容易的检测出那些未经声明的变量,避免其变为隐藏的全局变量,造成隐患。
在函数的开始应先用 var 关键字声明函数中要使用的局部变量,注释变量的功能及代表的含义,且应以字母顺序排序。每个变量单独占一行,以便添加注释。这是因为 JavaScript 中只有函数的 {} 表明作用域,用 var 关键字声明的局部变量只在函数内有效,而未经 var 声明的变量则被视为全局变量。我们来看下清单 3。
清单 3. 局部变量声明
<script language="javascript"> var valueA = "a"; var valueB = "b"; function f1() { var valueA = "c"; alert("valueA="+valueA); //output: valueA=c valueB = "d"; alert("valueB="+valueB); //output: valueB=d } f1(); alert("valueA="+valueA); //output: valueA=a alert("valueB="+valueB); //output: valueB=d </script>
从上例的输出惊奇地发现,用 var 声明过的变量 valueA 和没有声明的变量 valueB 是有区别的。特别需要注意的是,在函数内部用 var 声明的变量为局部变量,这样可以有效地避免因局部变量和全局变量同名而产生的错误。
函数的声明
函数也应在调用前进行声明,内部函数应在 var 声明内部变量的语句之后声明,可以清晰地表明内部变量和内部函数的作用域。
此外,函数名紧接左括号'('之间,而右括号')'和后面的'{'之间要有个空格,以清楚地显示函数名以其参数部分,和函数体的开始。若函数为匿名 / 无名函数,则 function 关键字和左括号'('之间要留空格,否则可能误认为该函数的函数名为 function。
清单 4. 内部函数声明
<script language="javascript"> var innerA = 1; function outF() { var innerA = 2; function _inF() { alert("valueA="+innerA); } _inF(); } outF(); //output: valueA=2 _inF(); //error: innerF is not defined </script>
从清单 4 的输出可以看出,inF() 函数仅在 outF() 函数的内部生效,局部变量 innerA 对内部函数的作用域生效。这样的编码方式使得变量和函数的作用域变得清晰。
语句
对于简单语句而言,需要提及的仍然是分号必要性,同时,一行最多有一个语句。如果一个赋值语句是用函数和对象来赋值,可能需要跨多行,一定切记要在赋值语句末加上分号。
这是因为 JavaScript 中,所有表达式都可以当语句,遇换行符时会解析为表达式的结束,此时不规范的换行和分号的丢失,可能引入新的错误。
对于复合语句,if, for, while, do, switch, try … catch 等代码体,函数定义的函数体,对象的定义等都需要放在花括号'{}'里面。
'{' 应在行末,标志代码块的开始。
'}' 应在一行开头,标志代码块的结束,同时需要和'{'所在行的开始对齐,以表明一个完整的复合语句段。这样可以极大地提高代码的可阅读性,控制逻辑能清晰地表现出来。
被包含的代码段应该再缩进 4 个空格。
即使被包含的代码段只有一句,也应该用花括号'{}'包含。尽管不用花括号代码也不会错,但如若需要增加语句的话,则较容易因花括号遗漏而引起的编译错误或逻辑错误。
return语句在使用时也需慎重,如果用表达式的执行作为返回值,请把表达式和 return 放在同一行中,以免换行符被误解析为语句的结束而引起返回错误。return 关键字后若没有返回表达式,则返回 undefined。构造器的默认返回值为 this。
清单 5. return 表达式