2007年3月13日

JavaScript中的编码惯例

这篇文章描述的是在JavaScript程序中的一些编码的惯例和规则,是从Sun 公司的文档Java的编码惯例得到灵感的,它经过了很大的修改因为JavaScript不是Java

对于一个软件来说,它的长期价值是与代码的编写质量成正比的,在其整个生命周期,一个程序将经历过许多人的眼睛和双手。如果一个程序能够清晰地沟通它的结构和特性,在不久的将来它被修改的时候就不会那么容易的崩溃。

编码惯例有助于减少编码的的脆弱性。

所有的JavaScript代码会直接暴露给公众,所以它应当具有出版那样的品质。

整洁的代码是有价值的!

JavaScript文件

JavaScript程序应当被存储和发表在.js 文件中。

JavaScript不应当被内含在HTML文件中,除非代码清晰地处理一次会话,在HTML里的JavaScript代码增加了页的体积并也不利于缓存和压缩。

<script src=filename.js>尽可能地不要放在body标签之内,这能减少脚本造成的对其它的页面组件延迟的现象。没必要使用languagetype属性,他们属于服务器而不是script标签的,他们用来决定MIME(多用途的网际邮件扩充协议)类型。译者按:对于xHTML必须要加上type属性。

代码缩进

缩进的尺度是4个空格,避免使用Tab,因为(到写这篇文章的21世纪为止)没有一个关于Tab使用的规范。使用空格会造成文件变大,但是对于本地网络来说,大小无关紧要,并且这个差异已经被minification消除了。

行的长度

避免一行代码超过80个字符,如果一条语句不适合单行的时候,有必要切断它。

  • 切断换行在逗号之后
  • 切断换行在任何操作符之后
  • 切断的下一行要缩进8个空格

在操作符之后切断换行,减少了那些像被分号的插入带来的复制粘贴错误。

注释

多用注释吧!对于那些过了段时间想了解你写代码的含义的人(甚至包括你自己),这非常有用。注释必须是“恰当的”和“清晰的”,就像代码他们在做注释一样。一个意外的金砖可能被感激,挫折和愤怒就不会。(An occasional nugget of humor might be appreciated. Frustrations and resentments will not)

保持注释和修改一致是很重要的,错误的注释难以让人理解和阅读。

让注释变得意味深长,把精力放到那些不是马上可见的事情上,不要浪费读者的时间像这样:

i = 0; // Set i to zero.

一般使用行注释,块注释保持统一匀称的格式。

变量声明

所有的变量在使用之前必须被声明,JavaScript本身不需要这样,但是这样做使程序更如果读懂,也有助于发现那些可能被暗暗地变成“全局的”的没有被声明的变量。

一个函数应当有一个单独的var语句来声明所有属与它的局部变量,这个var语句也应该被放置在这个函数最开始的位置。

每个变量和关于它的注释使用单独的一行是首选的,它们应该依据字母顺序排列。

     var currentEntry, // currently selected table entry
        level,        // indentation level
        size;         // size of table

JavaScript没有块域(block scope),所以在块里面定义变量搞糊涂那些对C家族语言富有经验的程序员。

不要给一个变量和参数与外部区域的变量以相同的名称,JavaScript可以重新定义变量名称,但这也增加了程序被看错的可能性。

尽量不要使用全局变量。

函数声明

所有的函数在使用之前必须被声明,内部函数要在局部变量声明之后,这样能使代码更清晰地显示处于闭包之间。

在函数名称和((左括弧)之间不应该有空格,在) (右括弧){ (左大括弧)之间应该有一个空格。函数内容应该缩进4个空格,} (右大括弧)应与函数头对齐。

    function outer(c, d) {
        var e = c * d;

        function inner(a, b) {
            return (e * a) + b;
        }

        return inner(0, 1);
    }

全局的方法应该被最小化。

在JavaScript,函数和对象可以放到任何表达式允许的地方,所以K+R的大括弧形式被使用了。这提供了最复杂的结构的最好的可读性。如果一个方法是一个匿名函数,那么function( (左括弧)之间应该放置一个空格,如果空格被忽略了,看起来就好像函数的名字是function一样,引起错误的阅读。

    function getElementsByClassName(className) {
        var results = [];
        walkTheDOM(document.body, function (node) {
            var a,                  // array of class names
                c = node.className, // the node's classname
                i;                  // loop counter

// If the node has a class name, then split it into a list of simple names.
// If any of them match the requested name, then append the node to the set of results.

            if (c) {
                a = c.split(' ');
                for (i = 0; i < a.length; i += 1) {
                    if (a[i] === className) {
                        results.push(node);
                        break;
                    }
                }
            }
        });
        return results;
    }

    div.onclick = function (e) {
        return false;
    };

    that = {
        method: function () {
            return this.datum;
        },
        datum: 0;
    };

名称

名称应当由26个大小写字母(A .. Z, a .. z),10个阿拉伯数字 (0 .. 9), 及_ (下划线)组成。避免使用国际性的字符,因为它们不是在哪都可以执行的很好。不要在名称中使用$符号(美元符号)或者\符号(反斜线符号)

不要使用_ (下划线)作为名称的第一个字符,因为这一般被习惯于用于声明“私有变量”但实际上它并不是私有的。如果“私有”是非常重要的,请使用私有成员提供的方式。避免使用任何缺乏论证的方式。

大多数变量和函数应该以小写字母开头。

那些将用于new 前缀的构造函数应当使用大写字母开头,如果不使用new会发生糟糕的事情,所以大写给了使用上提供了一个重要的提示。

全局变量应该全部被大写。(JavaScript没有宏或常量,这不是为了显示那些JavaScript没有的的特性。)

语句

简单的语句

每行至少包含一条语句,每个简单语句最后要插入一个分号“;”,注意那些要分配一个函数或对象的语句也必须以分号结尾。

JavaScript允许任何的表达式作为语句使用,这可能会遮蔽一些错误,尤其是在分号之前插入的时候。最恰当的表达式被用于语句应该是在赋值和调用中。

复合语句

复合语句是那些被圈起在{ } (大括弧)中的一系列语句。

  • 被圈起的语句前要缩进4个空格。
  • { (左大括弧)要在开始符合语句这一行的结尾。
  • } (右大括弧)应该新起一行,并和前面左大括弧相对齐。
  • 大括弧应当圈住所有语句,甚至一个单行的语句,在当他们是控制结构的一部分的时候,比如if语句或for语句的时候。这有助于增加新的语句在出现bug的时候。

标签(Labels)

语句的标签是可选的,只有以下这些语句需要标签:whiledoforswitch

return语句

一个带值return语句不要在值的左右使用( )(小括弧)。返回值表达式必须与return关键字同行以避免分号的插入。

if语句

if形式的语句应该以下面的方式出现:

    if (condition) {
        statements;
    }
    
    if (condition) {
        statements;
    } else {
        statements;
    }
    
    if (condition) {
        statements;
    } else if (condition) {
        statements;
    } else {
        statements;
    } 

注意if statements总是要使用大括弧的。

for语句

for 形式的语句应该以下面的方式出现:

    for (initialization; condition; update) {
        statements;
    }

    for (variable in object) {
        statements;
    } 

第一种形式用于数组。

第二种形式用于对象。这可以知道被加入到对象原型Object.prototype的成员,被枚举出来。这可以知道程序的结构:

    for (variable in object) {
        if (object.hasOwnProperty(variable)) {
            statements;
        }
    } 

注意for statements总是要使用大括弧的。

while语句

while 形式的语句应该以下面的方式出现:

    while (condition) {
        statements;
    } 

注意while statements总是要使用大括弧的。

do语句

do形式的语句应该以下面的方式出现:

    do {
        statements;
    } while (condition); 

注意do statements总是要使用大括弧的。与其他的符合语句不同,do语句总是以分号结尾。

switch语句

switch形式的语句应该以下面的方式出现:

    switch (expression) {
    case expression:
        statements;
    default:
        statements;
    }

每个case与switch对齐,避免过度缩进。

除了default的每组语句应当以breakreturnthrow结尾,不要遍历。

try语句

try形式的语句应该以下面的方式出现:

    try {
        statements;
    } catch (variable) {
        statements;
    }

    try {
        statements;
    } catch (variable) {
        statements;
    } finally {
        statements;
    } 

continue语句

避免使用continue语句,它使函数的控制流变的不清晰。

with语句

with语句不应当被使用

空白区域

在逻辑不同块上插入空白可以提高程序的可读性。

在如下情况下空白应当被使用。

  • 一个关键字后跟着一个左括弧,他们应该由一个空格分开。
    while (true) {
  • 在一个函数值和他们的左括弧之间应该插入一个空格,这有助于区别关键字和函数符号。(译者注:这是说在function之后直接有左括弧的情况。)
  • 所有的二元算子除了. (句点)( (左括弧) and [ (左中括弧)之外都要与他们操作者隔开一段距离。
  • 一元算子没必要和它的操作者用空格隔开。
  • 每个在for语句之内的语句后面的分号之后都放置一个空格。
  • 每个逗号后要放置一个空格。

额外的建议

{}[]

使用{}来代替new Object(),使用[] 代替new Array()

当成员的名字是连续整型时请使用数组,当成员的名字是任意的字符和名称的时候请使用对象。

, (逗号) 操作符

避免使用逗号,除了非常规则地在for语句中使用。(这不包括那些使用在对象形式,数组形式,var语句中和参数形式中。)

块区域

在JavaScript中没有块区域,只有方法有区域。不要使用块,除了使用复合语句的时候。

赋值表达式

避免在ifwhile语句的条件中使用赋值表达式。

    if (a = b) {

是正确声明?或者是

    if (a == b) {

才是呢?避免构造那些不容易确定是否正确的形式。

===!== 操作符

大多数情况下,使用===!==是更好的选择,==!=会进行类型的强制转换。确切一步说就是不要使用==来比较同为假的值。

捣乱的加减号

小心点,不要在+符号后用一个+++符号,这样的写法会引起混淆,在他们之间插入空格会使你意图更加清晰。

    total = subtotal + +myInput.value;

更好的写法是

    total = subtotal + (+myInput.value);

这样+ +不至于被看成++符号了。

eval是魔鬼

eval函数是JavaScript中最被滥用的特征,避免使用它。

eval类似的,不要使用Function构造器,不要把字符串传给setTimeoutsetInterval语句。

特别声明,文章翻译于 Code Conventions for the JavaScript Programming Language
版权由原作者所有。

没有评论: