snandy / JS-Style-Guide

JavaScript代码风格

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JDC 前端 JavaScript 代码规范

内容列表

  1. 文件
  2. 缩进
  3. 对象
  4. 数组
  5. 字符串
  6. 属性
  7. 变量
  8. 条件表达式和等号
  9. 语句
  10. 函数
  11. 类型转换

文件

  • JavaScript 文件使用无 BOM 的 UTF-8 编码。

为什么? UTF-8 编码具有更广泛的适应性。BOM 在使用程序或工具处理文件时可能造成不必要的干扰,比如Mac系统中的换行符问题

缩进

  • 使用 4 个空格。

    // bad
    function fn() {
    ∙∙var name;
    }
    // good
    function fn() {
    ∙∙∙∙var name;
    }
  • 每个独立语句结束后必须换行。

    // bad
    user.setCode(1); user.setName('admin'); user.setPwd('123456');
    
    // good
    user.setCode(1);
    user.setName('admin');
    user.setPwd('123456');
  • ifelseswitchcaseforwhile: 后1个空格。

    // bad
    if(a > b) {
    
    }
    // good
    if (a > b) {
    
    }
    
    // bad
    for(var i = 0; i < 5; i++) {
        // ...
    }
    // good
    for (var i = 0; i < 5; i++) {
        // ...
    }
  • 赋值语句两边各 1 个空格

    // bad
    name='John';
    
    // good
    name = 'John';
  • 两元运算符(==, >, <等)两边各 1 个空格。

    // bad
    if (a==b) {
    
    }
    
    // good
    if (a == b) {
    
    }
  • 函数参数之间 1 个空格。

    // bad
    function ajax(url,param,success) {
        // ...
    }
    
    // good
    function ajax(url, param, success) {
        // ...
    }
  • 左大括号前 1 个空格。

    // bad
    function ajax(url, param, success){
        // ...
    }
    if (a > b){
    
    }
    
    // good
    function ajax(url, param, success) {
        // ...
    }
    if (a > b) {
    
    }
  • 一元运算符(++--)前后不加空格。

    // bad
    ++ sum;
    total --;
    
    // good
    ++sum;
    total--;
  • 语句始终使用分号结尾,forfunctionifswitchtrywhile 除外,不要依赖于引擎隐式插入。

    // bad
    function fn() {
        // ...
    };
    // good
    function fn() {
        // ...
    }
    
    // bad
    for (var i = 0; i < 5; i++) {
        // ...
    };
    // good
    for (var i = 0; i < 5; i++) {
        // ...
    }
  • 不要将逗号放前面。

    // bad
    var hero = {
        firstName: 'Bob'
      , lastName: 'Parr'
      , heroName: 'Mr. Incredible'
      , superPower: 'strength'
    };
    
    // good
    var hero = {
      firstName: 'Bob',
      lastName: 'Parr',
      heroName: 'Mr. Incredible',
      superPower: 'strength'
    };
  • 起首的大括号跟在关键字的后面,且大括号前留有一个空格。

    // bad
    if (a > b)
    {
        // ...
    }
    // good
    if (a > b) {
        // ...
    }
    
    // bad
    function test(){
        console.log('test');
    }
    // good
    function test() {
        console.log('test');
    }
    
    // bad
    dog.set('attr',{
        age: '1 year',
        breed: 'Bernese Mountain Dog'
    });
    // good
    dog.set('attr', {
        age: '1 year',
        breed: 'Bernese Mountain Dog'
    });
  • 数组成员以逗号分隔,逗号后加 1 个空格。

    // bad
    var arr = [1,2,3,4];
    
    // good
    var arr = [1, 2, 3, 4];
  • 小括号作为函数调用时函数名与左小括号之间没有空格。

    // bad
    func ();
    
    // good
    func();
  • 小括号作为强制运算符时左括号前加 1 个空格。

    // bad
    return(x + y);
    
    // good
    return (x + y);
  • 行的长度不应超过80个字符,如果超过应当在运算符(逗号,加号等)后换行。下一行增加两级缩进(8个空格)。

    // bad
    doSomething(argument1, argument2, argument3, argument4, argument5);
    doSomething(argument1, argument2, argument3, argument4, 
        argument5);
    
    // good
    doSomething(argument1, argument2, argument3, argument4, 
            argument5);
  • 在单行注释符后留一个空格。

    // bad
    //this is comment
    
    
    // good
    // this is comment
  • 在多行注释的结束符前留一个空格,使星号对齐。

    // bad
    /*
      this is comment
    */
    
    // good
    /*
       this is comment
     */
  • 不要把注释写在多行注释的开始符、结束符所在行。

    // bad
    /* start
    
    end */
    /*
    here is line 1
    here is line 2
     */    
    
    // good
    /*
       start
       end
     */
    /*
       here is line 1
       here is line 2
     */         

返回列表

对象

  • 2.1 使用对象直接量创建对象。

    // bad
    var item = new Object();
    
    // good
    var item = {};
  • 2.2 不要使用 保留字 当 key,IE8 里有 bug, 查看更多

    // bad
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    // good
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };
  • 2.3 使用可读性更好的同义词来替代保留字。

    // bad
    var superman = {
      class: 'alien'
    }
    
    // good
    var superman = {
      type: 'alien'
    }

返回列表

数组

  • 3.1 使用数组直接量定义数组。

    // bad
    var items = new Array();
    
    // good
    var items = [];
  • 3.2 如果你不知道数组的长度,使用 push。

    var someStack = [];
    
    
    // bad
    someStack[someStack.length] = 'abababa';
    
    // good
    someStack.push('abababa');
  • 3.3 复制数组使用 slice。

    // bad
    var len = items.length;
    var itemsCopy = [];
    
    for (var i = 0; i < len; i++) {
      itemsCopy[i] = items[i]
    }
    
    // good
    var itemsCopy = items.slice();
  • 3.4 使用 slice 将伪数组的对象转成数组。

    var foo = document.querySelectorAll('.foo');
    var nodes = Array.prototype.slice.call(foo);

返回列表

字符串

  • 4.1 使用单引号定义字符串。

    // bad
    var name = "Capt. Janeway";
    
    // good
    var name = 'Capt. Janeway';
  • 4.2 超过80个字符的字符串采用加号 +, 多行显示。

    // bad
    var errorMessage = 'This is a super error that was thrown because of Batman. When you stop how Batman had anything to do with this, you would get nowhere fast.';
    
    // bad
    var errorMessage = 'This is a super error that was thrown because \
    of Batman. When you stop how Batman had anything to do \
    with this, you would get nowhere fast.';
    
    // good
    var errorMessage = 'This is a super error that was thrown because ' 
            + 'of Batman. When you stop how Batman had anything to do '
            + 'with this, you would get nowhere fast.';
  • 4.3 HTML属性使用双引号,即单引号在外层,双引号在内层。

    // bad
    var html = "<a href='http://www.jd.com'>京东</a>";
    
    // good
    var html = '<a href="http://www.jd.com">京东</a>';
  • 4.4 编程时使用 join 而不是字符串连接来构建字符串。

 var items;
 var messages;
 var i, length;

 messages = [{
     state: 'success',
     message: 'This one worked.'
 },{
     state: 'success',
     message: 'This one worked as well.'
 },{
     state: 'error',
     message: 'This one did not work.'
 }];

 length = messages.length;

 // bad
 function inbox(messages) {
   items = '<ul>';

   for (i = 0; i < length; i++) {
     items += '<li>' + messages[i].message + '</li>';
   }

   return items + '</ul>';
 }

 // good
 function inbox(messages) {
   items = [];

   for (i = 0; i < length; i++) {
     items[i] = messages[i].message;
   }

   return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
 }
 ```

**[返回列表](#table-of-contents)**


## <a name="properties">属性</a>

- [6.1](#6.1) <a name='6.1'></a> 使用点号 `.` 访问对象属性。

 ```javascript
 var luke = {
   jedi: true,
   age: 28,
 };

 // bad
 var isJedi = luke['jedi'];

 // good
 var isJedi = luke.jedi;
 ```

- [6.2](#6.2) <a name='6.2'></a> 当使用变量访问属性时使用中括号 `[]`。

 ```javascript
 var luke = {
   jedi: true,
   age: 28,
 };

 function getProp(prop) {
   return luke[prop];
 }

 var isJedi = getProp('jedi');
 ```

**[返回列表](#table-of-contents)**


## <a name="variables">变量</a>

- [7.1](#7.1) <a name='7.1'></a> 使用 `var` 来声明变量,否则会产生全局变量,避免污染全局命名空间。

 ```javascript
 // bad
 superPower = new SuperPower();

 // good
 var superPower = new SuperPower();
 ```
 
- [7.2](#7.2) 命名采用驼峰式,第一个单词小写,之后的单词首字母大写。

 ```javascript
 // bad
 var nickname = 'John';
 var nick_name = 'John';

 // good
 var nickName = 'John';
 ```
 
- [7.3](#7.3) 常量名全部用大写字母。

 ```javascript
 // bad
 var pi = 3.1415926;

 // good
 var PI = 3.1415926;
 ```


- [7.4](#7.4) 避免单个字符名,变量名应具有描述意义(计数器除外)。

 ```javascript
 // bad
 function q() {
     // ...stuff...
 }

 // good
 function query() {
     // ..stuff..
 }
 ```

- 类(构造器)名首字母大写,用名词。

 ```javascript
 // bad
 function person(name, age) {
     this.name = name;
     this.age = age;
 }

 // good
 function Person(name, age) {
     this.name = name;
     this.age = age;
 }
 ```    
 
- [7.2](#7.2) <a name='7.2'></a> 使用多个 `var` 以及新行声明多个变量。

 ```javascript
 // bad
 var items = getItems(),
     goSportsTeam = true,
     dragonball = 'z';

 // good
 var items = getItems();
 var goSportsTeam = true;
 var dragonball = 'z';
 ```

- [7.3](#7.3) <a name='7.3'></a> 就近声明,用时声明,更自然的在视角范围内。

 ```javascript
 // bad
 var i, len;
 var goSportsTeam = true;
 var dragonball = 'z';
 
 // ...
 	
 for (i = 0; i < len; i++) {
 	// ...
 }

 // good
 var goSportsTeam = true;
 var dragonball = 'z';
 
 // ...
 	
 for (var i = 0, len = arr.length; i < len; i++) {
 	// ...
 }
 ```

- [7.4](#7.4) <a name='7.4'></a> 最后声明未赋值的变量,当你想引用之前已赋值变量的时候很有用。

 ```javascript
 // bad
 var width;
 var height;
 var $div = $('#nav');
 
 // good
 var $div = $('#nav');
 var width = $div.width();
 var height = $div.height();
 
 ```

- [7.5](#7.5) <a name='7.5'></a> 变量应先声明后使用,避免 `变量提升` 现象产生。

 ```javascript
 // bad
 function fn() {
     doStaff(width, height);
     var width = $div.width() || 0;
     var height = $div.height() || 0;
 }

 // good
 function fn() {
     var width = $div.width() || 0;
     var height = $div.height() || 0;
     doStaff(width, height);
 }
 ```

- [7.6](#7.6) <a name='7.6'></a> 分组声明:变量多且有明显相关性时。

 ```javascript
 // bad
 var x, y, z, width, height;

 // good
 var x, y, z;
 var width, height;
 ```
 
- 前缀参考

 <table>
 	<thead>
 		<tr><td>前缀</td><td>类型</td><td>示例</td></tr>
 	</thead>
 	<tbody>
 		<tr><td>is, can has</td><td>Boolean</td><td>isPass</td></tr>
 		<tr><td>get</td><td>Getter</td><td>getName</td></tr>
 		<tr><td>set</td><td>Setter</td><td>setName</td></tr>
 		<tr><td>i, j, k</td><td>iterator</td><td></td></tr>
 		<tr><td>el</td><td>HTMLElement</td><td>elNav</td></tr>
 		<tr><td>$</td><td>jQuery Object</td><td>$nav</td></tr>
 	</tbody>
 </table>

**[返回列表](#table-of-contents)**

## <a name="conditionals">条件表达式和等号</a>

- [8.1](#8.1) <a name='8.1'></a> 严格比较使用  `===`  和  `!==` ,宽松比较使用 `==`  和  `!=`。多数时候请使用`严格比较`。
- [8.2](#8.2) <a name='8.2'></a> 条件表达式的转换内部执行ES规范里抽象方法的 `ToBoolean`, 遵循以下规则:

 + **对象** 转换为 **true**
 + **Undefined** 转化为 **false**
 + **Null** 转换为 **false**
 + **Boolean** 转换为 **布尔自身的值**
 + **Number** 如果是 **+0, -0, or NaN** 转换为 **false**,其它转换成 **true**
 + **String** 如果是 空字符串 `''` 转换成 **false** , 其它转化成 **true**

 ```javascript
 if ([0]) {
   // true
   // An array is an object, objects evaluate to true
 }
 ```

- [8.3](#8.3) <a name='8.3'></a> 使用快捷方式。

 ```javascript
 // bad
 if (name !== '') {
   // ...stuff...
 }
 // good
 if (name) {
   // ...stuff...
 }

 // bad
 if (collection.length > 0) {
   // ...stuff...
 }
 // good
 if (collection.length) {
   // ...stuff...
 }
 
 // bad
 if ($nav.length > 0) {
   // ...stuff...
 }
 // good
 if ($nav.length) {
   // ...stuff...
 }
 ```
 
**[返回列表](#table-of-contents)**

## <a name="blocks">语句</a>

- [9.1](#9.1) <a name='9.1'></a> 所有多行语句的块使用大括号。

 ```javascript
 // bad
 if (test)
   return false;

 // good
 if (test) return false;

 // good
 if (test) {
   return false;
 }

 // bad
 function() { return false; }

 // good
 function() {
   return false;
 }
 ```

- [9.2](#9.2) <a name='9.2'></a> `if` 和 `else` 块, 把 `else` 和第一个块的结束行放在一行。

 ```javascript
 // bad
 if (test) {
   thing1();
   thing2();
 }
 else {
   thing3();
 }

 // good
 if (test) {
   thing1();
   thing2();
 } else {
   thing3();
 }
 ```

**[返回列表](#table-of-contents)**

## <a name="functions">函数</a>

- 函数的长度控制在 50 行以内。

> 为什么?将过多的逻辑单元混在一个大函数中,难以维护。一个清晰易懂的函数应该完成单一的逻辑单元。复杂的操作应进一步分解,通过函数的调用来体现流程。

> 不可分割的特定算法逻辑允许例外。

- 函数的参数控制在 5 个以内,过多参数会导致维护难度增大。

> 为什么? 有些函数的参数并非作为算法的输入,而是对算法的某些分支条件判断之用,此类参数建议通过一个JS对象 options 传递。

> 某些情况下,如使用 AMD/CMD Loader 的 require 加载多个模块时,其 callback 可能会存在较多参数,因此对函数参数的个数不做强制限制。

- [5.1](#5.1) <a name='5.1'></a> 使用函数声明替代函数表达式。

 ```javascript
 // bad
 var foo = function () {
 };

 // good
 function foo() {
 }
 ```

- [5.2](#5.2) <a name='5.2'></a> 函数表达式。

 ```javascript
 // immediately-invoked function expression (IIFE)
 (function() {
     console.log('Welcome to the Internet. Please follow me.');
 })();
 ```

- [5.3](#5.3) <a name='5.3'></a> 不要将一个函数定义非函数块内,如 `if` 、 `while` 语句等。虽然浏览器允许这么干,但在各个浏览器中 <a href="http://w3help.org/zh-cn/causes/SJ9002" target="_blank">表现不一致</a>。

 ```javascript
 if (boo) {
     function bar() {alert(1);}    
 } else {
     function bar() {alert(2);}
 }
 ```


- [5.4](#5.4) <a name='5.4'></a> 参数不要命名为  `arguments`,该名在函数内自动创建。

 ```javascript
 // bad
 function nope(name, options, arguments) {
   // ...stuff...
 }

 // good
 function yup(name, options, args) {
   // ...stuff...
 }
 ```

**[返回列表](#table-of-contents)**

## <a name="type-casting--coercion">类型转换</a>

- [10.1](#10.1) <a name='10.1'></a> 字符串。

 ```javascript
 //  => this.reviewScore = 9;

 // bad
 var totalScore = this.reviewScore + '';

 // good
 var totalScore = String(this.reviewScore);
 ```

- [10.2](#10.2) <a name='10.2'></a> 数字使用 `parseInt` 且总是带上类型转换的基数。

 ```javascript
 var inputValue = '4';

 // bad
 var val = new Number(inputValue);

 // bad
 var val = +inputValue;

 // bad
 var val = inputValue >> 0;

 // bad
 var val = parseInt(inputValue);

 // good
 var val = Number(inputValue);

 // good
 var val = parseInt(inputValue, 10);
 ```

- [10.3](#10.3) <a name='10.3'></a> 出于 [性能考虑](http://jsperf.com/coercion-vs-casting/3), `parseInt` 不能满足要求时,使用位操作符 `>>` 转换,请注释说明。

 ```javascript
 // good
 /**
  * 此处对性能要求较高,不采用 parseInt 转换,使用 >> 会更快.
  */
 var val = inputValue >> 0;
 ```

- [10.4](#10.4) <a name='10.4'></a> **注意:** 当使用位移操作要小心,数字以 64 位存储,但 `>>` 最大以 32位运算。因此能转换的最大数字是 2,147,483,647。 超过该范畴的会出现错误:

 ```javascript
 2147483647 >> 0 //=> 2147483647
 2147483648 >> 0 //=> -2147483648
 2147483649 >> 0 //=> -2147483647
 ```

- [10.6](#10.5) <a name='10.5'></a> 布尔。

 ```javascript
 var age = 0;

 // bad
 var hasAge = new Boolean(age);

 // good
 var hasAge = Boolean(age);

 // good
 var hasAge = !!age;
 ```

**[返回列表](#table-of-contents)**

About

JavaScript代码风格

License:MIT License


Languages

Language:HTML 100.0%