JavaScript 推荐书写规范

自己写JavaScript也有一些年头了, 前些时候看Douglas的JSLint和他推荐的写法, 深有感触, 也见过不少JSer使用了他的规范, 但, 很多地方, 我却不能认同. 当然, 写法什么的, 最终还是看个人, 哪种写法效率更高, 就用哪种. 下面我就对比Douglas的规范, 说说我推荐的写法.

  1. JavaScript文件及引用
    根据需要将JavaScript代码放入单独的*.js文件中, 这些需要一般可能是指: 代码量较大, 代码被多个页面重用, 为了方便维护等. <script>标签因尽量放在<head>中, 并且标注type=”text/javascript”. 对于普通网页, 放在<body>结束之后, 有需要时甚至是<body>之中也是可以接受的. 但对于JavaScript密集的网页及WebApp, 应尽量避免.
  2. 缩进
    空格和Tab都可以接受, 但最好不要混用.
  3. 换行
    代码书写时要尽量保证其可读性, 自然每一行不应该过于长, 但不推荐无语义的换行. 换行应该能表达一个逻辑片段, 分组等意义.
  4. 注释及空行
    根据代码的需要进行注释, 在一个代码片段开始的前一行使用 // 注释该片段的作用, 对于难以理解的单行代码, 使用 // 注释在该行代码之后. 对于一个完整的, 或者相对重要的功能块, 使用 /* */ 在其上方第二行进行注释, 上方第一行留空. 如果结尾不明显, 容易与之后的代码混淆, 也可以在该功能块结束后再使用 /* */ 进行注释. 对于容易理解的代码, 也应该根据功能或者逻辑进行分组, 中间用空行隔开.
  5. 变量的声明和定义
    声明所有变量, 不过类似于 global.abc = 123; (浏览器中为window)这样的语句也是可以接受的. 随时声明变量能够帮助避免很多作用域的问题, 反之, 类似的问题可能会成为极大的困扰. 从个人来讲, 即使你非常清楚变量的作用域, 也应声明变量, 或者使用类似于global.abc = 123; 这样的形式定义全局变量. 当然, 语义化是永远需要注意的, 这点也适用于下面的函数声明.
    根据逻辑的进行声明变量, 有些变量, 比如在一个闭包中会被多个逻辑使用, 或者从意义上应该是独立与其他逻辑的, 应该放在闭包的最上方, 而部分仅仅会在某个逻辑中使用的变量, 则应该在该逻辑开始, 且该变量使用前声明. 如果该逻辑需要的变量较多, 容易与其他变量冲突, 可以考虑将该逻辑放入一个闭包中. 需要注意的是, 有些语句或许并不适合包含声明变量的代码, 比如if.
    另外, 不推荐使用一个var语句声明大量变量, 将变量分组, 并按意义上的先后顺序进行排序或许更好. 如:

    var id;
    var width, height;
    var left, top;

    当需要在声明的同时定义变量时, 通常我的做法是一个var语句只对应一个变量. 同时, 避免使用不必要的全局变量, 但不要担心局部变量和全局变量或闭包中的变量重名, 如果我们已经很清楚各自作用域的范围, 为了避免重名而给变量名添加各种前后缀, 或者缩写变量名的做法, 只会使代码变得更难理解.

  6.  函数声明和定义
    一般使用function语句进行函数声明, 且声明应放在当前闭包的最下方. 一般情况下, 一个函数主要是处理一个逻辑中某一个从意义上简单, 但代码量较大或者重用率较高的功能. 如果将函数声明在前面, 反而会影响我们直观地获知逻辑结构, 让本末倒置. 另一方面, 如果函数名足够语义化, 对于多数功能, 我们甚至可以略过函数体, 直接通过函数名来完成逻辑的阅读.
    对于声明和定义, 推荐使用这样的格式, 注意哪些地方有空格:

    /* 普通声明 */
    function abc() {
        //代码
    }
    /* 匿名函数赋值 */
    var fn1 = function () { return true; }; //单个语句可以写成一行
    var fn2 = function () {
        if (true)
            return true;
        else
            return false;
    };

    另外, 只有一些非常通用的函数适合作为全局函数(除非当前项目的JavaScript代码量非常少). 其他时候, 需要根据逻辑和意义来确定函数声明的位置. 闭包是JavaScript最美好的东西之一, 一定要善于利用. 它能够让代码具有更明显的结构. 有时需要建立一个立即执行的函数来实现一个闭包, 推荐这样的写法:

    (function () {
        //代码
    })();

  7. 命名
    尽量使用字母(A~Z, a~z)数字(0~9)和下划线(_)命名变量. 一般情况使用类似于myFirstName这样的驼峰状命名规则, 但如果变量的值代表一个类, 则首字母应该大写, 如: MyClass.  一些由于实现必须要求出现在逻辑结构之外的变量, 建议在其前后加双下划线标注. 如:

    var __inc__ = 0;
    function inc() { __inc__++; }

    但多数情况下(当结构相对简单时), 可以使用闭包来避免.
    对于一些有特别意义的全局变量, 比如当一个全局变量能决定是否执行某一个功能块, 以及部分常量, 推荐使用全大写命名, 单词之间使用下划线隔开, 如OPEN_DEBUG.
    另外, 尽量使用英文命名变量, 即使你的英文不够好. 退一万步, 如果使用拼音, 不要过度缩写. 顺便中英文混合虽然可以让人看到很 “快乐”, 但还是不要这样的好 .

  8. 语句
    每一行最多只包含一个语句, 需要分号的地方一定要加上分号. 包括这样的 语句: var fn = function () {}; 因为这实际上是一个赋值语句.
    对于控制结构, 如果只有一条语句, 可以将大括号去掉.
    另外, return是一个特定的语句, 并不是一个函数, 所以一般情况下, 不要在return之后使用(). 当然, 有时你可能会需要()帮你排除换行的歧义. 类似的还有typeof.
    continue有时会很有用, 所以完全没有必要回避. 至于with, 我很少用.
  9. 空格
    合理使用空格能够提高代码的可读性, 具体需要使用的情况如下:
    控制结构中的标示与()之间, ()与后面的语句或者复合语句之间. 如: while (true) {}.
    多数运算符左右应添加空格, 如 var a = 1 + 2; var b = true ? 1 : 0;
    逗号(,), 分号(;)后如果不换行则需要添加一个空格.
  10. 其他建议
    使用 {} 代替 new Object(), [] 代替 new Array();
    在创建一个类型的实例时, 不管构造函数的实参个数是否为0, 都应该加上(), 如new Object()不应写为new Object.
    如果你已经足够熟悉JavaScript了, 那么使用这样的语句也未尝不可:

    var a = true;
    if (a = !a)
        alert(‘hello’);

    同时, ==和!=在多数情况下都是适用的, 所以没必要处处都使用===和!==.
    除此之外, 我觉得一个漂亮的JavaScript代码一定是充分并正确利用了JavaScript语言特性的, 至于这些特性, 就很难一一描述了. 不过, 如果你真的喜欢JavaScript, 请去感受它.

所以只是个人建议而已, 具体怎么落实, 酌情.