代码规范

确立并遵守代码规范非常重要,这会让你的代码风格一致、可预测,并且可读性更强。团队新成员通过学习代码规范可以很快进入开发状态,并写出让团队其他成员易于理解的代码。

在开源社区和邮件组中关于编代风格的争论一直不断。(比如关于代码缩进,用tab还是空格?)因此,如果你打算在团队内推行某种编码规范时,要做好应对各种反对意见的心理准备,而且要吸取各种意见。确定并遵守代码规范非常重要,任何一种规范都可以,这甚至比代码规范中的具体约定是怎么样的还要重要。

缩进

代码如果没有缩进就几乎不能读了,而不一致的缩进会使情况更加糟糕,因为它看上去像是遵守了规范,但真正读起来却没那么顺利。因此规范地使用缩进非常重要。

有些开发者喜欢使用tab缩进,因为每个人都可以根据自己的喜好来调整tab缩进的空格数,有些人则喜欢使用空格缩进,通常是四个空格。这都无所谓,只要团队每个人都遵守同一个规范即可,本书中所有的示例代码都采用四个空格的缩进写法,这也是JSLint所推荐的。(译注:电子版中看到的是用tab缩进,本译文也保留使用tab缩进。)

那么到底什么时候应该缩进呢?规则很简单,花括号里的内容应当缩进,包括函数体、循环(dowhileforfor-in)体、if语句、switch语句和对象字面量里的属性。下面的代码展示了如何正确地使用缩进:

  1. function outer(a, b) {
  2. var c = 1,
  3. d = 2,
  4. inner;
  5. if (a > b) {
  6. inner = function () {
  7. return {
  8. r: c - d
  9. };
  10. };
  11. } else {
  12. inner = function () {
  13. return {
  14. r: c + d
  15. };
  16. };
  17. }
  18. return inner;
  19. }

花括号

在特定的语句中应当总是使用花括号,即便是在可省略花括号的情况下也应当如此。从技术角度讲,如果iffor中只有一个语句,花括号是可以省略的,但最好还是不要省略,这会让你的代码更加工整一致而且易于修改。

假设有这样一段代码,for循环中只有一条语句,你可以省略掉这里的花括号,而且不会有语法错误:

  1. // 不好的方式
  2. for (var i = 0; i < 10; i += 1)
  3. alert(i);

但如果过了一段时间,你给这个循环添加了另一行代码会怎样?

  1. // 不好的方式
  2. for (var i = 0; i < 10; i += 1)
  3. alert(i);
  4. alert(i + " is " + (i % 2 ? "odd" : "even"));

第二个alert实际上在循环体之外,但这里的缩进会让你迷惑。从长远考虑最好还是写上花括号,即便是在只有一个语句的语句块中也应如此:

  1. // 更好的方式
  2. for (var i = 0; i < 10; i += 1) {
  3. alert(i);
  4. }

同理,if条件句也应当如此:

  1. // 不好的方式
  2. if (true)
  3. alert(1);
  4. else
  5. alert(2);
  6. // 更好的试
  7. if (true) {
  8. alert(1);
  9. } else {
  10. alert(2);
  11. }

左花括号的位置

开发人员对于左大括号的位置有着不同的偏好,在同一行呢还是在下一行?

  1. if (true) {
  2. alert("It's TRUE!");
  3. }

或者:

  1. if (true)
  2. {
  3. alert("It's TRUE!");
  4. }

在这个例子中,这个问题只是个人偏好问题。但有时候花括号位置的不同会影响程序的执行,因为JavaScript会“自动插入分号”。JavaScript对行尾是否有分号并没有要求,它会自动将分号补全。因此,当函数的return语句返回了一个对象字面量,而对象的左花括号和return又不在同一行时,程序的执行就和预期的不同了:

  1. // 警告:返回值和预期的不同
  2. function func() {
  3. return
  4. {
  5. name: "Batman"
  6. };
  7. }

可以看出程序作者的意图是返回一个包含了name属性的对象,但实际情况不是这样。因为return后会填补一个分号,函数的返回值就是undefined。这段代码等价于:

  1. // 警告:返回值和预期的不同
  2. function func() {
  3. return undefined;
  4. // 下面的代码不会运行…
  5. {
  6. name: "Batman"
  7. };
  8. }

总结一下好的写法,在特写的语句中总是使用花括号,并且总是将左花括号与上一条语句放在同一行:

  1. function func() {
  2. return {
  3. name: "Batman"
  4. };
  5. }

关于分号也值得注意:和花括号一样,应当总是使用分号,尽管在JavaScript解析代码时会补全行末省略的分号,但严格遵守这条规则,可以让代码更加严谨,同时可以避免前面例子中所出现的歧义。

 空格

空格的使用同样有助于改善代码的可读性和一致性。在写英文句子的时候,在逗号和句号后面会使用间隔,在JavaScript中,你可以按照同样的逻辑在表达式(相当于逗号)和语句结束(相对于完成了某个“想法”的表达)后面添加间隔。

适合使用空格的地方包括:

  • for循环中的分号之后,比如for (var i = 0; i < 10; i += 1) {...}
  • for循环中初始化多个变量,比如for (var i = 0, max = 10; i < max; i += 1) {...}
  • 用于分隔数组元素的逗号之后,比如var a = [1, 2, 3];
  • 对象属性后的逗号以及名值对之间的冒号之后,比如var o = {a: 1, b: 2};
  • 函数参数中,比如myFunc(a, b, c)
  • 函数声明的花括号之前,比如function myFunc() {}
  • 匿名函数表达式function之后,比如var myFunc = function () {};

另外,我们推荐在运算符和操作数之间也添加空格。也就是说在+-*=<><=>====!==&&||+=符号前后都添加空格。

  1. // 适当且一致的空格给代码留了“呼吸空间”,使代码更易读
  2. var d = 0,
  3. a = b + 1;
  4. if (a && b && c) {
  5. d = a % c;
  6. a += d;
  7. }
  8. // 反模式,缺少或者不正确的空格使得代码不易读
  9. var d= 0,
  10. a =b+1;
  11. if (a&& b&&c) {
  12. d=a %c;
  13. a+= d;
  14. }

最后,还应当注意,最好在花括号旁边添加空格:

  • 在函数、if-else语句、循环、对象字面量的左花括号之前补充空格
  • 在右花括号和else或者while之间补充空格

垂直空白的使用经常被我们忽略,你可以使用空行来将代码单元分隔开,就像文学作品中使用段落进行分隔一样。