javascript 编程规范

http://blog.bingo929.com/dojo-javascript-style-guide.html

Any violation to this guide is allowed if it enhances readability.

所有的代码都要变成可供他人容易阅读的。

快读参考

核心 API 请使用下面的风格:

结构 规则 注释
模块 小写 不要使用多重语义(Never multiple words)
骆驼
公有方法 混合 其他的外部调用也可以使用 lower_case(),这样的风格
公有变量 混合
常量 骆驼 或 大写

下面的虽然不是必要的,但建议使用:

结构 规则
私有方法 混合,例子:_mixedCase
私有变量 混合,例子:_mixedCase
方法(method)参数 混合,例子:_mixedCase, mixedCase
本地(local)变量 混合,例子:_mixedCase, mixedCase

 

命名规范

1.变量名称 必须为 小写字母。
2.类的命名使用骆驼命名规则,例如:

 

   Account, EventHandler

 

3.常量 必须 在对象(类)或者枚举变量的前部声明。枚举变量的命名必须要有实际的意义,并且其成员 必须 使用骆驼命名规则或使用大写:

 

var NodeTypes = {
    Element : 1,
    DOCUMENT: 2
}

 

4.简写单词 不能使用 大写名称作为变量名:

 

getInnerHtml(), getXml(), XmlDocument

 

5.方法的命令 必须 为动词或者是动词短语:

 

obj.getSomeValue()

 

6.公有类的命名 必须 使用混合名称(mixedCase)命名。
7.CSS 变量的命名 必须 使用其对应的相同的公共类变量。
8.私有类的变量属性成员 必须 使用混合名称(mixedCase)命名,并前面下下划线(_)。例如:

 

var MyClass = function(){
   var _buffer;
   this.doSomething = function(){
   };
}

 

9.变量如果设置为私有,则前面 必须 添加下划线。

 

this._somePrivateVariable = statement;

 

10.通用的变量 必须 使用与其名字一致的类型名称:

 

setTopic(topic) // 变量 topic 为 Topic 类型的变量

 

11.所有的变量名 必须 使用英文名称。
12.变量如有较广的作用域(large scope),必须使用全局变量;此时可以设计成一个类的成员。相对的如作用域较小或为私有变量则使用简洁的单词命名。
13.如果变量有其隐含的返回值,则避免使用其相似的方法:

 

getHandler(); // 避免使用 getEventHandler()

 

14.公有变量必须清楚的表达其自身的属性,避免字义含糊不清,例如:

MouseEventHandler,而非 MseEvtHdlr。
请再次注意这条规定,这样做得的好处是非常明显的。它能明确的表达表达式所定义的含义。例如:  
dojo.events.mouse.Handler // 而非 dojo.events.mouse.MouseEventHandler

  

15.类/构造函数 可以使用 扩展其基类的名称命名,这样可以正确、迅速的找到其基类的名称:
 EventHandler
 UIEventHandler
 MouseEventHandler
  基类可以在明确描述其属性的前提下,缩减其命名:
   MouseEventHandler as opposed to MouseUIEventHandler.

特殊命名规范

  1. 术语 “get/set” 不要和一个字段相连,除非它被定义为私有变量。
  2. 前面加 “is” 的变量名 应该 为布尔值,同理可以为 “has”, “can” 或者 “should”。
  3. 术语 “compute” 作为变量名应为已经计算完成的变量。
  4. 术语 “find” 作为变量名应为已经查找完成的变量。
  5. 术语 “initialize” 或者 “init” 作为变量名应为已经实例化(初始化)完成的类或者其他类型的变量。
  6. UI (用户界面)控制变量应在名称后加控制类型,例如: leftComboBox, TopScrollPane。
  7. 复数必须有其公共的名称约定(原文:Plural form MUST be used to name collections)。
  8. 带有 “num” 或者 “count” 开头的变量名约定为数字(对象)。
  9. 重复变量建议使用 “i”, “j”, “k” (依次类推)等名称的变量。
  10. 补充用语必须使用补充词,例如: get/set, add/remove, create/destroy, start/stop, insert/delete, begin/end, etc.
  11. 能缩写的名称尽量使用缩写。
  12. 避免产生歧义的布尔变量名称,例如:
      isNotError, isNotFound 为非法
  13. 错误类建议在变量名称后加上 “Exception” 或者 “Error”。
  14. 方法如果返回一个类,则应该在名称上说明返回什么;如果是一个过程,则应该说明做了什么。

文件

缩进请使用 4 个空白符的制表位。
如果您的编辑器支持 文件标签_(file tags),请加添如下的一行使我们的代码更容易阅读:

 

// vim:ts=4:noet:tw=0:

 

译注:老外用 VIM 编辑器比较多,此条可以选择遵循。

代码折叠必须看起来是完成并且是合乎逻辑的:

 

var someExpression = Expression1
    + Expression2
    + Expression3;

var o = someObject.get(
    Expression1,
    Expression2,
    Expression3
);

 

注:表达式的缩进与变量声明应为一致的。
注:函数的参数应采用明确的缩进,缩进规则与其他块保持一致。

变量

  1. 变量必须在声明初始化以后才能使用,即便是 NULL 类型。
  2. 变量不能产生歧义。
  3. 相关的变量集应该放在同一代码块中,非相关的变量集不应该放在同一代码块中。
  4. 变量应该尽量保持最小的生存周期。
  5. 循环/重复变量的规范:
    1. 只有循环控制块的话,则必须使用 FOR 循环。
    2. 循环变量应该在循环开始前就被初始化;如使用 FOR 循环,则使用 FOR 语句初始化循环变量。
    3. “do … while” 语句是被允许的。
    4. “break” 和 “continue” 语句仍然允许使用(但请注意)。
  6. 条件表达式
    1. 应该尽量避免复杂的条件表达式,如有必要可以使用临时布尔变量。
    2. The nominal case SHOULD be put in the “if” part and the exception in the “else” part of an “if” statement.
    3. 应避免在条件表达式中加入块。
  7. 杂项
    1. 尽量避免幻数(Magic numbers),他们应该使用常量来代替。
    2. 浮点变量必须指明小数点后一位(即使是 0)。
    3. 浮点变量必须指明实部,即使它们为零(使用 0. 开头)。

布局

  1. 普通代码段 应该 看起来如下:

     

    while (!isDone){
            doSomething();
        isDone = moreToDo();
    }
  2. IF 语句 应该 看起来像这样:

     

    if (someCondition){
            statements;
    } else if (someOtherCondition){
        statements;
    } else {
        statements;
    }
  3. FOR 语句 应该 看起来像这样:

     

    for (initialization; condition; update){
            statements;
    }
  4. WHILE 语句 应该 看起来像这样:

     

    while (!isDone) {
            doSomething();
        isDone = moreToDo();
    }
  5. DO … WHILE 语句 应该 看起来像这样:

     

    do {
            statements;
    } while (condition);
  6. SWITCH 语句 应该 看起来像这样:

     

    switch (condition) {
    case ABC:
        statements;
        //  fallthrough
    case DEF:
        statements;
        break;
    default:
            statements;
        break;
    }
  7. TRY … CATCH 语句 应该 看起来像这样:

     

    try {
        statements;
    } catch(ex) {
        statements;
    } finally {
        statements;
    }
  8. 单行的 IF – ELSE,WHILE 或者 FOR 语句也 必须 加入括号,不过他们可以这样写:

     

    if (condition){ statement; }
    while (condition){ statement; }
    for (intialization; condition; update){ statement; }

空白

  1. 操作符 建议 使用空格隔开(包括三元操作符)。
  2. 下面的关键字 避免使用 空白隔开:
    • break
    • catch
    • continue
    • do
    • else
    • finally
    • for
    • function (如果为匿名函数,例如:var foo = function(){}; )
    • if
    • return
    • switch
    • this
    • try
    • void
    • while
    • with
  3. 下面的关键字必须使用空白隔开:
    • case
    • default
    • delete
    • function (如果为申明,例如:function foo(){}; )
    • in
    • instanceof
    • new
    • throw
    • typeof
    • var
  4. 逗号(,) 建议 使用空白隔开。
  5. 冒号(:) 建议 使用空白隔开。
  6. 点(.) 在后部 建议 使用空白隔开。
  7. 点(.) 避免 在前部使用空白。
  8. 函数调用和方法 避免 使用空白,例如: doSomething(someParameter); // 而非 doSomething (someParameter)
  9. 逻辑块 之间使用空行。
  10. 声明 建议 对齐使其更容易阅读。

注释

  1. 生涩的代码就 没有必要 添加注释了,首先您需要 重写 它们。
  2. 所有的注释请使用英文。
  3. 从已解决的方案到未开发的功能,注释 必须 与代码相关。
  4. 大量的变量申明后 必须 跟随一段注释。
  5. 注释需要说明的是代码段的用处,尤其是接下来的代码段。
  6. 注释 没有必要 每行都添加。

文档

下面提供了一些基本的函数或者对象的描述方法:

  • 总结(summary): 简短的表述此函数或者对象实现的目的
  • 描述(description): 对于此函数或者类的简短的描述
  • 返回(return): 描述此函数返回什么(并不包括返回类型)

基本函数信息

 

function(){
    // summary: Soon we will have enough treasure to rule all of New Jersey.
    // description: Or we could just get a new roomate.
    //          Look, you go find him.  He don't yell at you.
    //          All I ever try to do is make him smile and sing around
    //          him and dance around him and he just lays into me.
    //          He told me to get in the freezer 'cause there was a carnival in there.
    // returns:  Look, a Bananarama tape!
}

 

对象函数信息

没有返回值描述

 

{
    // summary: Dingle, engage the rainbow machine!
    // description:
    //          Tell you what, I wish I was--oh my g--that beam,
    //          coming up like that, the speed, you might wanna adjust that.
    //          It really did a number on my back, there. I mean, and I don't
    //          wanna say whiplash, just yet, cause that's a little too far,
    //          but, you're insured, right?
}

 

函数的声明

在有的情况下,对于函数的调用和声明是隐义(invisible)的。在这种情况下,我们没有办法在函数中加入说明等(供程序调用)。如果您遭遇了这种情况,您可以使用一个类来封装函数。

注:此此方法只能在函数没有初始化的参数情况下。如过不是,则它们会被忽略。

 

dojo.declare(
    "foo",
    null,
    {
        // summary: Phew, this sure is relaxing, Frylock.
        // description:
        //              Thousands of years ago, before the dawn of
        //              man as we knew him, there was Sir Santa of Claus: an
        //              ape-like creature making crude and pointless toys out
        //              of dino-bones, hurling them at chimp-like creatures with
        //              crinkled hands regardless of how they behaved the
        //              previous year.
        // returns: Unless Carl pays tribute to the Elfin Elders in space.
        }
);


<h3>参数</h3>
<ol>
    <li>简单类型
   简单的类型的参数可以直接在函数参数定义中注释说明。
[cc lang="javascript"]function(/*String*/ foo, /*int*/ bar)...

 

  • 可变类型参数
      下面是几个修饰符供参考:
    • ? 可选参数
    • … 说面参数范围不确定
    • 数组
    function(/*String?*/ foo, /*int...*/ bar, /*String[]*/ baz)...
  • 全局参数描述
     如果你想增加一个描述,你可以将它们移至初始化块。

      基本信息格式为: *关键字* 描述字段 ( *key* Descriptive sentence)
      参数和变量的格式为: *关键字* ~*类型*~ 描述字段 ( *key* ~*type*~ Descriptive sentence)
      注: *关键字* 和 ~*类型*~ 可以使用任何字母和数字表述。

      function (foo, bar) {
          // foo: String
          //          used for being the first parameter
          // bar: int
          //          used for being the second parameter
      }

      变量

      由于实例变量、原型变量和外部变量的声明是一致的,所以有很多的方法声明、修改变量。具体的如何定义和定位应在变量最先出现的位置指明变量的名称、类型、作用域等信息。

      function foo() {
          // myString: String
          // times: int
          //          How many times to print myString
          // separator: String
          //          What to print out in between myString*
          this.myString = "placeholder text";
          this.times = 5;
      }
      foo.prototype.setString = function (myString) {
          this.myString = myString;
      }
      foo.prototype.toString = function() {
          for(int i = 0; i < this.times; i++) {
              dojo.debug(this.myString);
              dojo.debug(foo.separator);
              }
      }
      foo.separator = "=====";

      对象中的变量注释

      应使用和对象值和方法一致的标注方式,比如在他们声明的时候:

      {
          // key: String
          //          A simple value
          key: "value",
          // key2: String
          //          Another simple value
      }

      返回值

      因为函数可以同时返回多个不同(类型)的值,所以应每个返回值之后加入返回类型的注释。注释在行内注释即可,如果所有的返回值为同一类型,则指明返回的类型;如为多个不同的返回值,则标注返回类型为”mixed”。

      function() {
              if (arguments.length) {
                      return "You passed argument(s)"; // String
              } else {
              return false; // Boolean
          }
      }

       

       

      声明变量必须加上 var 关键字,除了在for(;;)循环等语句中,原则上不允许使用连续声明。因为连续声明的效率不如分开声明高,而且很容易手误致其暴露到全局作用域下。

      常量,全部大写。

      变量名,不能使用拼音,英文单词以驼峰风格组织起来。

      分号,能加的地方都加(基本上除了for, function, if, switch, try, while外),防止因为这个问题导致压缩失败。

      自定义类,只能用于UI库的构建,业务代码不准私自定义类。

      原则上不允许使用伪对象(String, Number,Boolean),直接用其字面量。

      原则上不允许使用Array与Object,直接用其字面量[], {}。

      谨慎处理this,防止绑定失效,指向window,建议使用that引用它。

      若想调用函数自身,禁止使用命名函数表达式,在目标函数的第一行编写以下代码实现,详解请google 《命名函数表达式揭秘》:

      var self = arguments.callee;

      禁止扩展原生对象的原型,特别是Object.prototype。

      禁止在页面上对某个元素绑定事件,即下面的代码风格

      <a href="aaaa" jump="bbb" onclick="goto(this.jump)">跳转到某页面</a>

      禁止使用IE的条件注释,一压缩就没有了。

      var f = function () {
          /*@cc_on if (@_jscript) { return 2* @*/  3; /*@ } @*/
      };

      禁止块内函数声明,详解请google《命名函数表达式揭秘》。

      if (x) { //ng
        function foo() {}
      }
        
      if (x) {
        var foo = function() {}
      }

      for-in 循环只能用于object。

      禁止使用多行字符串,因为在编译时, 不能忽略行起始位置的空白字符; "\" 后的空白字符会产生奇 怪的错误; 虽然大多数脚本引擎支持这种写法, 但它不是 ECMAScript 的标准规范。

      var myString = 'A rather long string of English text, an error message \
                      actually that just keeps going and going -- an error \
                      message to make the Energizer bunny blush (right through \
                      those Schwarzenegger shades)! Where was I? Oh yes, \
                      you\'ve got an error and all the extraneous whitespace is \
                      just gravy.  Have a nice day.';

      原则上不允许字符串拼接HTML代码,请使用前台模板或后台模板。

      字符串字面量,使用 ' 优于 "。

      注释,使用JSDoc。

      每一行不宜过长,写完一段代码后请用IDE把它格式化一下。

      为元素添加自定义变量,统一使用"data-"前缀,放便与HTML5的"data-*"机制相衔接。

      禁止jQuery使用一行以上的链式操作,非常难读。

      元素的选择,多使用ID选择器,类选择器,标签选择器,慎用子元素结构伪类与位置伪类(nth- child,:first,:eq,:gt)

      在已有jQuery对象搜找附近的元素节点,不建议用使用多级的find寻找,而使用相关的遍历函数

      JavaScript程序应尽量放到外部的JS文件中,以便压缩与缓存。

      标准特性优于非标准特性(如果类库有提供,优先使用类库中的函数)。

      $("XXXX").find("YYYY").find("ZZZZ"); //ng
      $("XXXX").next() //或者nextUntil, nextAll, prev, prevAll, prevUntl, children, closest, 
        
      .siblings

      为元素添加事件时,考虑的顺序是delegate > live > bind。

      jQuery在以下事件中存在问题 change resize mouseenter mouseleave mousewheel,大体上用不了事件代理,像mousewheel事件只能借助于插件。

      不在JS文件中留下未来确定不再使用的代码片段

      凡是被jQuery引用到的ID或类名都应该用js_作为前缀,警示其他人在调整样式时把它误删了。

      JS代码必须置于$$命名空间对象之内,所有函数的执行从main函数开始。

           ;;;$(function(){
      //...其他用到的变量
              var $$ = window.$$ = {
                //本页面私有的辅助函数1
                _assist1:function(){
        
                },
                //本页面私有的辅助函数2
                _assist2:function(){
        
                },
                //本页面私有的辅助函数3
                _assist3:function(){
        
                },
                //本页面私有的辅助函数4
                _assist4:function(){
        
                },
                //本页面私有的辅助函数5
                _assist5:function(){
        
                },
      //....更多的私有函数
                //功能1
                feature1:function(){
        
                },
                //功能2
                feature2:function(){
        
                },
                //功能3
                feature3:function(){
        
                },
                //功能4
                feature4:function(){
        
                },
                //功能5
                feature5:function(){
        
                },
                //从后台获取的JSON数据统一放到这个对象中,以便其他函数调用
                jsons:{},
      //....更多需求,一个需求对应一个函数
                main:function(){
                  $$.feature1();
                  $$.feature2();
                  $$.feature3();
                  $$.feature4();
      //....在main主函数中调用它们。
                }
              }
              $$.main();
            });

      从后台获取JSON数据的格式统一为

      $.getJSON(url,params,function(json){
           if(json && json.status === "1"){
             $.flash(json.msg);
             $$.jsons["xxxx"] = json;//将JSON保存起来
           }else{
             $.flash(json.msg,"error")
           }
      });
      $.post(url,params,function(json){
           if(json && json.status === "1"){
             $.flash(json.msg);
             $$.jsons["xxxx"] = json;
           }else{
             $.flash(json.msg,"error")
           }
      },"json");

      为了实现请求与执行回调相分离,我们使用dependBy函数,这样就有效避免多层嵌套的回调,让代码的易懂性大大提高。

      $.dependBy(["list_configs"],$$.jsons,function(){
           var json = $$.jsons.ist_configs;
           //......其他代码
      });

      暂时想到这么多,如果你有什么好建议,不吝赐教。

    1. posted @ 2012-09-12 10:36  awp110  阅读(365)  评论(0编辑  收藏  举报