JavaScript编码规范


Bug----33条

1. 不要使用’==’和’!=’,使用’===’和’!==’替代

  • 等级:Major

  • 原因:==和!=在判断值相等前会判断类型是否相等。这容易因为类型不同而造成错误。比如:它会认为表达式:’\t\r\n’==0是正确的。因此,要采用===和!==替代这两个符号。

  • 建议如下的方式:

    if (var === 'howdy') {
    ...
    }
  • 不建议如下的方式:

    if (var == 'howdy') {
    ...
    }
  • 例外:在判断函数是否为空的情况下,使用==或!=是可以的。在下边的例子中,如果foo没有被初始化,它默认的值是undefined而不是null。当然underfined更不会等于null了。因此这种情况应该使用==和!=。

    if (foo == null) {
    ...
    }

2. "DELETE"不能在数组中使用

  • 等级:Critical

  • 原因:delete函数可以用来删除任何的对象。数组是对象,因此可以被delete操作。但是如果这样使用了,就会在数组中产生一个undefined元素,无法从下标中反应出delete操作。

    从含有下标的元素中移除元素的适当方法有:

    Array.prototype.splice – 从数组中移除元素

    Array.prototype.pop – 从数组的尾端移除元素

    Array.prototype.shift – 从数组的开始移除元素

  • 建议如下的方式:

    var myArray = [ 'a', 'b', 'c', 'd' ];
    // removes 1 element from index 2
    removed = myArray.splice(2, 1);
    // myArray => ['a', 'b', 'd']
    console.log(myArray[2]); // outputs 'd'
  • 不建议如下的方式:

    var myArray = [ 'a', 'b', 'c', 'd' ];
    delete myArray[2];
    // Noncompliant. myArray => ['a', 'b', undefined, 'd']
    console.log(myArray[2]);
    // expected value was 'd' but output is 'undefined'

3. 不能使用"EVAL"和"ARGUMENTS"作为变量

  • 等级:Critical

  • 原因:在JavaScript中eval是一个将字符串转换为JavaScript代码执行的函数,而arguments则是JavaScript的一个内置对象。如果两者作为变量使用就会覆盖了原先的定义。同是,在较为严格的JavaScript检测中,这样做是不会通过的。

  • 建议如下的方式:

    result = 17;
    
    args++;
    
    ++result;
    
    var obj = {
    set p(arg) {
    }
    }; var result; try {
    }
    catch (args) {
    } function x(arg) {
    } function args() {
    } var y = function fun() {
    }; var f = new Function('args', 'return 17;'); function fun() {
    if (arguments.length == 0) {
    // do something
    }
    }
  • 不建议如下的方式:

    eval = 17; // Noncompliant
    
    arguments++; // Noncompliant
    
    ++eval; // Noncompliant
    
    var obj = {
    set p(arguments) {
    }
    }; // Noncompliant var eval; // Noncompliant try {
    }
    catch (arguments) {
    } // Noncompliant function x(eval) {
    } // Noncompliant function arguments() {
    } // Noncompliant var y = function eval() {
    }; // Noncompliant var f = new Function('arguments', 'return 17;'); // Noncompliant function fun() {
    if (arguments.length == 0) { // Compliant
    // do something
    }
    }

4. "FOR"循环在每次执行时,都要修改控制循环的值

  • 等级:Critical

  • 原因:如果for循环永远无法完成就会产生错误。即便不会产生错误,也会对以后的变量值造成无法确定的影响,因此不能够这样使用。

  • 建议如下的方式:

    for (i = 0; i < 10; i++) {
    // ...
    }
  • 不建议如下的方式:

    for (i = 0; i < 10; j++) { // Noncompliant
    // ...
    }

5. "FOR … IN"这种循环在每次操作前需要进行过滤判断

  • 等级:Major

  • 原因:"for … in"这种循环允许开发人员按照属性的名字遍历对象。不幸的是,这个属性的集合包括了对象自身和对象继承的对象的所有属性。如果程序不考虑这点就会出现错误。
    因此,对于每个”for … in”循环,都应该包括一个if判断来过滤你需要的属性。

  • 建议如下的方式:

    for (name in object) {
    if (object.hasOwnProperty(name)) {
    doSomething(name);
    }
    }
  • 不建议如下的方式:

    for (name in object) {
    doSomething(name); // Noncompliant
    }

6. "INDEXOF"的检测需要包括0

  • 等级:Major

  • 原因:大部分字符串或者数组的indexof方法的判断需要和-1而不是0作比较。因为0代表该元素存在于字符串或者数组中。因此所有的indexof(..)>0的判断都忽略的0这种情况,是一个典型的错误。

  • 建议如下的方式:

    var color = 'blue';
    var name = 'ishmael';
    var number = 123;
    var arr = [color, name];
    if (arr.indexOf('blue') >= 0) {
    // ...
    }
    if (arr[0].indexOf('ish') > - 1{
    // ...
    }
  • 不建议如下的方式:

    var color = 'blue';
    var name = 'ishmael';
    var number = 123;
    var arr = [color, name];
    if (arr.indexOf('blue') > 0) { // Noncompliant
    // ...
    }
    if (arr[0].indexOf('ish') > 0{ // Noncompliant
    // ...
    }

7. "NAN"不能用在比较中

  • 等级:Blocker

  • 原因:NAN不等于包括自身在内的任何值。因此与NAN作比较是得不到你需要的结果的,但是这种错误有可能会出现。事实上,判断值是否等于NAN最好的方法就是和它自己作比较即NAN!==NAN,因为正常的变量都是等于自身的,如果不等于自身成立,就说明这个值是NAN。

  • 建议如下的方式:

    if (a !== a) {
    console.log('a is not a number');
    } if (a === a) {
    console.log('a is not NaN');
    }
  • 不建议如下的方式:

    var a = NaN;
    if (a === NaN) { // Noncompliant; always false
    console.log('a is not a number'); // this is dead code
    } if (a !== NaN) { // Noncompliant; always true
    console.log('a is not NaN'); // this statement is not necessarily true
    }

8. "new"关键字应该和构造函数一起使用

  • 等级:Critical

  • 原因:new这个关键字应该在定义了构造函数的对象中使用。如果在其他地方使用就会出现错误因为没有构造方法可以供new调用。

  • 建议如下的方式:

    /**
    * @constructor
    */
    function MyClass() {
    this.foo = 'bar';
    } var someClass = function () {
    this.prop = 1;
    } var obj1 = new someClass; // Compliant
    var obj2 = new MyClass(); // Compliant regardless of considerJSDoc value
  • 不建议如下的方式:

    var someClass = 1;
    
    var obj1 = new someClass; // Noncompliant;
    

9. 不能使用”WITH”代码块

  • 等级:Major

  • 原因:使用with关键字在一些较为严格的JavaScript检测中会报错。然而,这并不是最糟的,诚然使用with可以方便的访问到对象中既定的属性,但是如果属性在对象中尚未定义,则访问范围就会扩大到全局,有可能覆盖某些重名的变量。显然这种效果完全依赖于被访问的对象,并且产生的危害是不可测的,因此with不能使用。

  • 建议如下的方式:

    var x = 'a';
    var foo = {
    y: 1
    }
    foo.y = 4;
    foo.x = 3;
    print(foo.x + ' ' + x); // shows: 3 a
  • 不建议如下的方式:

    var x = 'a';
    var foo = {
    y: 1
    }
    with (foo) { // Noncompliant
    y = 4; // updates foo.x
    x = 3; // does NOT add a foo.x property; updates x var in outer scope
    }
    print(foo.x + ' ' + x); // shows: undefined 3

10. "FOR"循环块里的控制数值增长的方向必须准确

  • 等级:Blocker

  • 原因:如果for循环里的控制变量增长方向错误则会导致for循环永远无法执行完成。虽然有时候构建无限循环是故意的,比如使用while构建无限循环。但是,大部分情况下是存在错误。

  • 建议如下的方式:

    for (var i = 0; i < strings.length; i++) {
    //...
    }
  • 不建议如下的方式:

    for (var i = 0; i < strings.length; i--) { // Noncompliant;
    //...
    }

11. 不要使用ARRAY和OBJECT的构造方法

  • 等级:Major

  • 原因:由于有着对变量的特定解释方法,数组的构造方法是容易出错的。如果超过一个参量,数组的长度将会等于参量的数量。然而,如果使用一个参量将会产生三种可能结果:

    如果这个参数是个数字并且是个正整数,则会产生一个长度等于该参数的数组;

    如果这个参数是个数字但是不是个正整数,将会抛出异常;

    其他情况下将会产生长度为1的数组。

  • 建议如下的方式:

    var a = [x1, x2, x3];
    var a2 = [x1, x2];
    var a3 = [x1];
    var a4 = [];
    var o = {};
    var o2 = {
    a: 0,
    b: 1,
    c: 2,
    'strange key': 3
    };
  • 不建议如下的方式:

    var a3 = new Array(x1); // Noncompliant and variable in results
    var a4 = new Array(); // Noncompliant. Results in 0-element array.
    var a1 = new Array(x1, x2, x3); // Noncompliant. Results in 3-element array.
    var o = new Object(); // Noncompliant
    var o2 = new Object(); // Noncompliant
    o2.a = 0;
    o2.b = 1;
    o2.c = 2;
    o2['strange key'] = 3;

12. 子表达式中不要出现赋值语句

  • 等级:Major

  • 原因:赋值语句在子表达式中容易产生错误,并且降低程序的可读性。像将==写成=是一种常见的错误。

  • 建议如下的方式:

    i = 42;
    doSomething(i);
    // or
    doSomething(i == 42); // Perhaps in fact the comparison operator was expected
  • 不建议如下的方式:

    doSomething(i = 42);
    
  • 例外:赋值语句可以在while循环或者关系表达式中出现。

    while ((line = nextLine()) != null) {
    ...
    } // Compliant while (line = nextLine()) {
    ...
    } // Compliant if (line = nextLine()) {
    ...
    } // Noncompliant

13. 内置对象不能被重载

  • 等级:Major

  • 原因:重载一个对象改变了它自身的行为可能会影响到代码中的其它对象。如果不小心重载内置对象可能会对其它的代码产生灾难性的危害。这条规则检测如下内置对象是否被重载:

    基本对象 - Object, Function, Boolean, Symbol, Error, EvalError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError;

    数据和时间- Number, Math, Date;

    文本处理-String, RegExp;

    各种数组- Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Unit16Array, Int32Array, Uint32Array, Float32Array, Float64Array;

    集合-Map, Set, WeakMap, WeakSet;

    结构化数据- ArrayBuffer, DataView, JSON;

    控制抽象的关键字-Promise;

    反射-Reflect,Proxy;

    国际化-Intl;

    非标准的对象-Generator, Iterator, ParallelArray, StopIteration.

14. 没有用的存储应该被及时的移除

  • 等级:Major

  • 原因:如果一个变量在赋值后没有被使用,则会产生无用的存储。只有尽快释放它,才不会对代码造成危害。即便不产生危害,对资源也是一种浪费。因此,要保证所有定义的变量都要被用到。

  • 建议如下的方式:

    function pow(a, b) {
    if (b == 0) {
    return 0;
    }
    var x = a;
    for (var i = 1, i < b, i++) {
    x = x * a;
    }
    return x;
    }
  • 不建议如下的方式:

    function pow(a, b) {
    if (b == 0) {
    return 0;
    }
    var x = a;
    for (var i = 1, i < b, i++) {
    x = x * a; //Dead store because the last return statement should return x instead of returning a
    }
    return a;
    }

15. 保证函数调用时传入的参数都被使用

  • 等级:Critical

  • 原因:在JavaScript中你可以在调用函数时传入比函数自身要求的更多的参数,但是,要保证额外的参数能够被使用。

  • 建议如下的方式:

    function doSomething(a, b) {
    compute(arguments);
    }
    doSomething(1, 2, 3) // Compliant
  • 不建议如下的方式:

    function say(a, b) {
    print(a + ' ' + b);
    }
    say('hello', 'world', '!'); // Noncompliant; last argument is not used

16. 不要在循环内部定义函数

  • 等级:Major

  • 原因:在循环内部定义函数会造成不可预料的结果,因为这样定义的函数生命周期很短,同时其中的变量值也会不断被更新。

  • 不建议如下的方式:

    var funs = [];
    for (var i = 0; i < 13; i++) {
    funs[i] = function () { // Non-Compliant
    return i;
    };
    }
    print(funs[0] ()); // 13 instead of 0
    print(funs[1] ()); // 13 instead of 1
    print(funs[2] ()); // 13 instead of 2
    print(funs[3] ()); // 13 instead of 3
    ...

17. 函数不能被二次定义

  • 等级:Major

  • 原因:这条规则检测在同一个作用域内是否有同名的函数。事实上,很有可能产生这种现象,但是JavaScript引擎只会执行最后一次声明的那个函数。这种重复声明函数的代码通常会带来bug并且会让代码很乱。

  • 建议如下的方式:

    fun(); // prints "foo"
    function fun() {
    print('foo');
    }
    fun(); // prints "foo" 或者是: fun(); // prints "foo"
    function fun() {
    print('foo');
    }
    fun(); // prints "foo"
    function printBar() {
    print('bar');
    }
    fun(); // prints "foo"
  • 不建议如下的方式:

    fun(); // prints "bar"
    // first declaration of the function
    function fun() {
    print('foo');
    }
    fun(); // prints "bar"
    // redeclaration of the "fun" function: this definition overrides the previous one
    function fun() {
    print('bar');
    }
    fun(); // prints "bar"

18. 关于HTML-STYLE的注释不能使用

  • 等级:Major

  • 原因:这种注释的风格不是JavaScript规范的一部分所以不能够使用

  • 建议如下的方式:

    // Compliant
    /* Compliant */
  • 不建议如下的方式:

    <!-- Noncompliant -->
    

19. 二元运算符两侧不能使用相同的式子

  • 等级:Critical

  • 原因:
    使用相同值的二元运算符往往会造成错误。这种情况的逻辑操作符,要么是个粘贴拷贝的错误,要么就是在浪费代码,需要修改。如果出现在布尔表达式中,结果就是可以确定的,没有意义。

  • 建议如下的方式:

    doZ();
    if (a == b) {
    doX();
    }
    if (a == b) {
    doW();
    }
    var j = 1;
    var k = 0;
  • 不建议如下的方式:

    if (a == a) { // always true
    doZ();
    }
    if (a != a) { // always false
    doY();
    }
    if (a == b && a == b) { // if the first one is true, the second one is too
    doX();
    }
    if (a == b || a == b) { // if the first one is true, the second one is too
    doW();
    }
    var j = 5 / 5; //always 1
    var k = 5 - 5; //always 0
  • 例外:在测试值是否是NAN情况下是可以使用的,因为只有NAN不等于自身。

    f(f !== f) { // test for NaN value
    console.log('f is NaN');
    }
    var i = 1 << 1; // Compliant
    var j = a << a; // Noncompliant

20. 嵌套的代码块不能为空

  • 等级:Major
  • 原因:大部分为空的嵌套代码块是忘记了,或者丢失了。这种代码块没有任何意义。
  • 不建议如下的方式:

    for (var i = 0; i < length; i++) {
    } // Empty on purpose or missing piece of code ?
  • 例外:如果代码块中嵌套着注释,则这个代码块可以为空。

21. 属性名称在文本对象中重复

  • 等级:Critical
  • 原因:JavaScript允许属性名在文本对象中重复。但是,将会以最后一次声明的属性为最终的值。因此,改变相同属性名的值将会产生意想不到的错误。并且在较为严格的检测中这种重复是不允许的。
  • 建议如下的方式:

    var data = {
    'key': 'value',
    '1': 'value',
    'key2': 'value',
    'key3': 'value',
    key4: 'value',
    \u006bey5: 'value',
    '\u006bey6': 'value',
    '\x6bey7': 'value',
    1b: 'value'
    }
  • 不建议如下的方式:

    var data = {
    'key': 'value',
    '1': 'value',
    'key': 'value', // Noncompliant - duplicate of "key"
    'key': 'value', // Noncompliant - duplicate of "key"
    key: 'value', // Noncompliant - duplicate of "key"
    key: 'value', // Noncompliant - duplicate of "key"
    'key': 'value', // Noncompliant - duplicate of "key"
    'key': 'value', // Noncompliant - duplicate of "key"
    1: 'value' // Noncompliant - duplicate of "1"
    }

22. 在”IF/ELSE IF”和”SWITCH/CASES”代码块中,不能出现相同的条件

  • 等级:Critical
  • 原因: 这两种分支代码块会执行第一个符合条件的语句,如果出现两个相同的条件,很有可能是copy/paste错误,或者是程序员考虑不周。无论是哪个都会产生错误。对于switch代码块,如果条件中存在break则不会执行接下来的条件,直接跳出该代码块。对于if代码块虽然没有break,但会覆盖前一个条件设定的值,出现错误。
  • 建议如下的方式:

    if (param == 1)
    openWindow();
    else if (param == 2)
    closeWindow();
    else if (param == 3)
    moveWindowToTheBackground();
    switch (i) {
    case 1:
    //...
    break;
    case 3:
    //...
    break;
    default:
    // ...
    break;
    }
  • 不建议如下的方式:

    if (param == 1)
    openWindow();
    else if (param == 2)
    closeWindow();
    else if (param == 1) // Noncompliant
    moveWindowToTheBackground();
    switch (i) {
    case 1:
    //...
    break;
    case 3:
    //...
    break;
    case 1: // Noncompliant
    //...
    break;
    default:
    // ...
    break;
    }

23. ==和!=不要用在FOR循环中控制终止条件

  • 等级:Critical
  • 原因:使用==和!=控制for循环的终止条件是比较危险的。因为可能造成无限循环。
  • 建议如下的方式:

    for (var i = 1; i <= 10; i += 2) // Compliant
    {
    //...
    }
  • 不建议如下的方式:

    for (var i = 1; i != 10; i += 2) // Noncompliant. Infinite; i goes from 9 straight to 11.
    {
    //...
    }
  • 例外:如果测试的是null则可以使用==和!=,比如:

    for (inti = 0; arr[i] != null; i++) {
    // ...
    }
    for (inti = 0; (item = arr[i]) != null; i++) {
    // ...
    }

24. 选择器得到的结果一定要用LENGTH判断

  • 等级:Critical
  • 原因:一旦使用选择器,你会想知道是否找到了所需的元素。因为选择器总是返回一个对象(或者DOM元素集合),最好的方式是判断返回对象的length属性。
  • 建议如下的方式:

    // Testing whether a selection contains elements.
    if ($('div.foo').length > 0) {
    // this code only runs if elements were found
    // ...
    }
  • 不建议如下的方式:

    if ($('div.foo')) { // Noncompliant
    // this code always runs, even when the selector didn't match any elements
    // ...
    }

25. SETTERS不能返回值

  • 等级:Critical
  • 原因:用set关键字定义的函数会自动的返回传出的值。因此,任何自定义的返回值都会被忽略,确切的说这是一种错误。
  • 建议如下的方式:

    var person = {
    // ...
    set name(name) {
    this.name = name;
    }
    }
  • 不建议如下的方式:

    var person = {
    // ...
    set name(name) {
    this.name = name;
    return 42; // Noncompliant
    }
    }

26. 用逻辑短路防止出现空的错误

  • 等级:Blocker
  • 原因:在测试元素是否为空时,需要注意使用逻辑短路防止对空元素进行操作,产生错误。
  • 建议如下的方式:

    if (str != null && str.length == 0) {
    console.log('String is empty');
    }
    if (str != undefined && str.length == 0) {
    console.log('String is empty');
    }
    if (str == null || str.length > 0) {
    console.log('String is not empty');
    }
    if (str == undefined || str.length > 0) {
    console.log('String is not empty');
    }
  • 不建议如下的方式:

    if (str == null && str.length == 0) {
    console.log('String is empty');
    }
    if (str == undefined && str.length == 0) {
    console.log('String is empty');
    }
    if (str != null || str.length > 0) {
    console.log('String is not empty');
    }
    if (str != undefined || str.length > 0) {
    console.log('String is not empty');
    }

27. 调用PARSEINT函数要带两个参数

  • 等级:Critical
  • 原因:parseInt函数有两个版本的,一个是只有一个参数的,而另一个是需要两个参数的。然而,旧版的浏览器不支持一个参数的parseInt方法。
  • 好的方法:

    parseInt("010", 10);
    
  • 不建议如下的方式:

    parseInt("010");  // Noncompliant; pre-2013 browsers may return 8
    

28. 在分支语句中,两个不同的分支不要执行相同的操作

  • 等级:Major
  • 原因:在switch语句中两不同的case执行相同的代码和在if语句中两个不同的条件执行相同的操作都是代码重复的表现,有时甚至会报错。因此,需要将两个条件进行合并。
  • 建议如下的方式:

    switch (i) {
    case 1:
    case 3:
    doSomething();
    break;
    case 2:
    doSomethingDifferent();
    break;
    default:
    doTheRest();
    }
    if ((a >= 0 && a < 10) || (a >= 20 && a < 50)) {
    doTheThing();
    else if (a >= 10 && a < 20) {
    doTheOtherThing();
    }
    else {
    doTheRest();
    } 或者是:
    switch (i) {
    case 1:
    doSomething();
    break;
    case 2:
    doSomethingDifferent();
    break;
    case 3:
    doThirdThing();
    break;
    default:
    doTheRest();
    }
    if (a >= 0 && a < 10) {
    doTheThing();
    else if (a >= 10 && a < 20) {
    doTheOtherThing();
    }
    else if (a >= 20 && a < 50) {
    doTheThirdThing();
    }
    else {
    doTheRest();
    }
  • 不建议如下的方式:

    switch (i) {
    case 1:
    doSomething();
    break;
    case 2:
    doSomethingDifferent();
    break;
    case 3: // Noncompliant; duplicates case 1's implementation
    doSomething();
    break;
    default:
    doTheRest();
    }
    if (a >= 0 && a < 10) {
    doTheThing();
    else if (a >= 10 && a < 20) {
    doTheOtherThing();
    }
    else if (a >= 20 && a < 50) {
    doTheThing(); // Noncompliant; duplicates first condition
    }
    else {
    doTheRest();
    }
    CompliantSolution:
    switch (i) {
    case 1:
    case 3:
    doSomething();
    break;
    case 2:
    doSomethingDifferent();
    break;
    default:
    doTheRest();
    }
    if ((a >= 0 && a < 10) || (a >= 20 && a < 50)) {
    doTheThing();
    else if (a >= 10 && a < 20) {
    doTheOtherThing();
    }
    else {
    doTheRest();
    }

29. 变量不要做没有用的增长

  • 等级:Critical
  • 原因:将变量增长或者递减而不进行存储是典型的代码冗余的表现,更有甚者会产生错误。
  • 建议如下的方式:

    var i = 0;
    i++;
  • 不建议如下的方式:

    var i = 0;
    i = i++; // Noncompliant; i is still zero

30. 不要重复使用变量或者方法名

  • 等级:Major
  • 原因:这条规则检验声明变量或方法时不要使用已经存在的名子。事实上,重复使用相同的名子在语法上是允许的,但是结果让人无法预测。因此可能会产生无法预测的错误。
  • 建议如下的方式:

    var a = 'foo';
    function otherName() {
    }
    console.log(a);
    function myFunc(arg) {
    var newName = 'event';
    }
    fun(); // prints "foo"
    function fun() {
    print('foo');
    }
    fun(); // prints "foo"
    function printBar() {
    print('bar');
    }
    printBar(); // prints "bar"
  • 不建议如下的方式:

    var a = 'foo';
    function a() {
    } // Noncompliant console.log(a); // prints "foo"
    function myFunc(arg) {
    var arg = 'event'; // Noncompliant, argument value is lost
    }
    fun(); // prints "bar"
    function fun() {
    console.log('foo');
    }
    fun(); // prints "bar"
    function fun() { // Noncompliant
    console.log('bar');
    }
    fun(); // prints "bar"

31. 变量不要重复声明

  • 等级:Major
  • 原因:这条规则检验变量是否被重复定义。这种重复定义的变量往往会造成无法预测的错误。
  • 建议如下的方式:

    var a = 'foo';
    var b = 'bar';
    function f(e) {
    var g = 'event';
    }
  • 不建议如下的方式:

    var a = 'foo';
    var a = 'bar'; // Non-Compliant
    function f(e) {
    var e = 'event'; // Non-Compliant
    }

32. 变量不能自己赋值给自己

  • 等级:Major
  • 原因:变量赋值给自己是没有意义的。要么是个代码冗余,要么是个错误。
  • 建议如下的方式:

    function setName(name) {
    this.name = name;
    }
  • 不建议如下的方式:

    function setName(name) {
    name = name;
    }

Misra----4条

1. 不能使用"CONTINUE"

  • 等级:Critical
  • 原因:continue是个非结构控制块。它会降低代码测试性,可读性和可维护性。应该使用结构化控制块(例如if)来代替。
  • 建议如下的方式:

    for (i = 0; i < 10; i++) {
    if (i != 5) { /* Compliant */
    alert('i = ' + i);
    }
    }
  • 不建议如下的方式:

    for (i = 0; i < 10; i++) {
    if (i == 5) {
    continue; /* Non-Compliant */
    }
    alert('i = ' + i);
    }

2. ”SWITCH”代码块至少有3个”CASE”

  • 等级:Minor
  • 原因:如果低于三个的话使用if会更方便些。
  • 建议如下的方式:

    if (variable == 0) {
    doSomething();
    } else {
    doSomethingElse();
    }
  • 不建议如下的方式:

    switch (variable) {
    case 0:
    doSomething();
    break;
    default:
    doSomethingElse();
    break;
    }

3. 逗号操作符不要在表达式中使用

  • 等级:Major
  • 原因:逗号操作符连接两个表达式,从左到右执行它们。这种方式不利于代码的可读性和可维护性,并且这种方式也可以用其它方式替代。
  • 建议如下的方式:

    a +=  2;
    i = a + b;
  • 不建议如下的方式:

    i = a += 2, a + b;  // What's the value of i ?
    
  • 例外:在for循环中的控制部分是可以使用逗号分割表达式的。

    for(i = 0, j = 5; i < 6; i++, j++) { ... }
    

4. 代码段不应该被注释掉

  • 等级:Minor
  • 原因: 开发人员不能注释代码,因为会影响代码可读性。不再使用的代码就删除。

5. 函数中没有使用过的变量应该被删除

  • 等级:Major
  • 原因:函数中没有被使用过的参数不会影响函数的操作结果,应该被删掉。
  • 建议如下的方式:

    function doSomething(b) {
    return compute(b);
    }
  • 不建议如下的方式:

    function doSomething(a, b) { // "a" is unused
    return compute(b);
    }
  • 例外:当函数存在返回值时,有些变量可能需要作为某些函数的标志。例如:

    $(['first','last']).each(function (i, value) {
    computeSomethingWithValue(value);
    });
    var myFirsCallBackFunction = function (p1, p2, p3, p4) { //unused p2 is not reported but p4 is
    return p1 + p3;
    }
    var mySecondCallBackFunction = function (p1, p2, p3, p4) { //unused p1, p2 and p3 are not reported
    return p4;
    }
    var myThirdCallBackFunction = function (p1, p2, p3, p4) { //unused p1 is not reported but p3 and p4 are
    return p2;
    }

Pitfall----19条

1. 保留字不能用作标识符

  • 等级:Critical
  • 原因:以下的单词是JavaScript保留字,用于JavaScript以后的拓展,不能作为标识符使用。

    await
    class
    const
    enum
    exports
    extends
    implements
    import
    interface
    let
    package
    private
    protected
    public
    static
    super
    yield
  • 建议如下的方式:

    var elements = document.getElementsByName('foo'); // Compliant
    
  • 不建议如下的方式:

    var package = document.getElementsByName('foo'); // Noncompliant
    var someData = { package: true }; // Compliant, as it is not used as an identifier here

2. “SWITCH”块中不能包括没有CASE关键词的分支

  • 等级:Critical
  • 原因:即便是合法的,这样做也会大大降低代码可读性,严重时,会造成意想不到的错误。

  • 建议如下的方式:

    Case1
    switch (day) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    doSomething();
    break;
    ...
    }
    Case2
    switch (day) {
    case MONDAY:
    break;
    case TUESDAY:
    compute(args); // put the content of the labelled "for" statement in a dedicated method
    break;
    /* ... */
    }
  • 不建议如下的方式:

    Case1,
    The code is syntactically correct but the behavior is not the expecte done
    switch (day) {
    case MONDAY:
    case TUESDAY:
    WEDNESDAY: // instead of "case WEDNESDAY"
    doSomething();
    break;
    ...
    }
    Case2,the code is correct and behaves as expected but is hardly readable
    switch (day) {
    case MONDAY:
    break;
    case TUESDAY:
    foo: for (i = 0; i < X; i++) {
    /* ... */
    break foo; // this break statement doesn't relate to the nesting case TUESDAY
    /* ... */
    }
    break;
    /* ... */
    }

3. 不能将”UNDEFINED”赋值给变量

  • 等级:Critical
  • 原因:undefined是一个属性尚未创建的标志。如果将它赋值给已经存在的属性,你将无法区分变量是否创建。更好的方式是你可以使用null代替。

  • 建议如下的方式:

    var myObject = {
    };
    // ...
    myObject.fname = null;
    // ...
    if (myObject.lname == undefined) {
    // property not yet created
    }
    if (myObject.fname == undefined) {
    // no real way of knowing the true state of myObject.fname
    }
  • 不建议如下的方式:

    var myObject = {
    };
    // ...
    myObject.fname = undefined; // Noncompliant
    // ...
    if (myObject.lname == undefined) {
    // property not yet created
    }
    if (myObject.fname == undefined) {
    // no real way of knowing the true state of myObject.fname
    }

4. 不要使用安位操作符

  • 等级:Major
  • 原因:JavaScript没有integer类型,但是它有安位操作符<<, >>, >>>, ~, &,I。这种操作会首先将float类型转换为integer类型,然后再转换回来,并不能像C那样高效。更何况,支持这种操作的浏览器也很少。

  • 建议如下的方式:

    if (a && b) {
    ...
    }
    var oppositeSigns = false;
    if ((x < 0 && y > 0) || (x > 0 && y < 0)) {
    oppositeSigns = true;
    }
  • 不建议如下的方式:

    if (a & b) {
    ...
    } // Noncompliant; & used in error var oppositeSigns = ((x ^ y) < 0); // Noncompliant; there's a clearer way to test for this

5. 构造方法不能单独使用

  • 等级:Major
  • 原因:有些工程师喜欢单独调用构造方法而不将值赋值给变量。这是有百害无一利的做法,因为这样构造的对象就无法在其它地方使用了。

  • 建议如下的方式:

    var something = new MyConstructor();  // Compliant
    
  • 不建议如下的方式:

    new MyConstructor(); // Non-Compliant
    

6. 要使用大括号作为范围控制

  • 等级:Major
  • 原因:虽然没有语法的错误,但是不使用大括号会降低代码的可读性。还有可能造成逻辑上的错误。

  • 建议如下的方式:

    if (condition) {
    executeSomething();
    checkSomething();
    }
  • 不建议如下的方式:

    // the two statements seems to be attached to the if statement, but that is only true for the first one:
    if (condition)
    executeSomething();
    checkSomething();

7. 函数的参数名不能相同。

  • 等级:Critical
  • 原因:函数的参数名应该不一样以防操作产生混乱。实际上,如果存在相同的参数名,最后一个参数将会覆盖前边相同的参数。这种做法是没有意义的,降低了可读性和可维护性。

  • 建议如下的方式:

    function compute(a, b, c) { // Compliant
    }
  • 不建议如下的方式:

    function compute(a, a, c) { // Noncompliant
    }

8. 函数调用的参数不要在新的一行里开始

  • 等级:Critical
  • 原因:因为“;”一行的结束符在JavaScript中不是必须的,如果函数调用的参数在新的一行开始就会让代码可读性大大降低。可能会导致错误和以后维护的问题。

  • 建议如下的方式:

    // define a function
    Either
    var fn = function () {
    //...
    }; // <-- semicolon added
    // then execute some code inside a closure
    (function () {
    //...
    }) ();
    Or
    var fn = function () {
    //...
    }(function () { // <-- start function call arguments on same line
    //...
    }) ();
  • 不建议如下的方式:

    var fn = function () {
    //...
    }(function () { // Noncompliant
    //...
    }) ();

9. 不要使用UNDERFINED作为变量

  • 等级:Critical
  • 原因:开发人员有可能使用undefined作为变量,但是这个关键字是区别变量是否创建的标志。如果被覆盖,你将无法区别变量是否存在。

  • 建议如下的方式:

    function foo() {
    var bob = 1; // anything is better than naming it 'undefined'
    if (nonExistantVar == undefined) {
    // ...
    }
    }
  • 不建议如下的方式:

    function foo() {
    var undefined = 1; // Noncompliant
    if (nonExistantVar == undefined) { // this logic doesn't work now
    // ...
    }
    }

10. 八进制不能被使用

  • 等级:Major
  • 原因:尽管JavaScript是完全支持八进制的,但是大部分开发人员不能熟练的使用八进制。他们可能会将八进制当做十进制数字来处理。

  • 建议如下的方式:

    var myNumber = 8;
    
  • 不建议如下的方式:

    var myNumber = 010;   // myNumber will hold 8, not 10 - was this really expected?
    

11. 只能在”WHILE”,”DO”和”FOR”中使用LABEL

  • 等级:Major
  • 原因:在任何代码块中都可以识别label,但是只能在”while”,”do”和”for”使用label。在其他结构中使用label都会使结构混乱,代码难以理解。

  • 建议如下的方式:

    myLabel: for (i = 0; i < 10; i++) { // Compliant
    print('Loop');
    break myLabel;
    }
  • 不建议如下的方式:

    myLabel: if (i % 2 == 0) { // Noncompliant
    if (i == 12) {
    print('12');
    break myLabel;
    }
    print('Odd number, but not 12');
    }

12. 源文件中不能有重复的模块

  • 等级:Major
  • 原因:如果存在重复的模块就会产生错误。

13. SWITCH的每个条件结尾都要有BREAK

  • 等级:Critical
  • 原因:如果条件中没有break,那么程序就会继续往下执行。虽然有时候这是开发人员有意设置的,但是更大可能的是代码错误。

  • 建议如下的方式:

    switch (myVariable) {
    case 1:
    foo();
    break;
    case 2:
    doSomething();
    break;
    default:
    doSomethingElse();
    break;
    }
  • 不建议如下的方式:

    switch (myVariable) {
    case 1:
    foo();
    break;
    case 2: // Both 'doSomething()' and 'doSomethingElse()' will be executed. Is it on purpose ?
    doSomething();
    default:
    doSomethingElse();
    break;
    }
  • 例外:以下情况,该规则认为是合理的:

    switch (myVariable) {
    case 0: // Empty case used to specify the same behavior for a group of cases.
    case 1:
    doSomething();
    break;
    case 2: // Use of return statement
    return;
    case 3: // Use of throw statement
    throw new IllegalStateException();
    case 4: // Use of continue statement
    continue;
    default: // For the last case, use of break statement is optional
    doSomethingElse();
    }

14. 不能在对象外使用THIS

  • 等级:Minor
  • 原因:如果在对象外使用this,它将指代全局的对象window。显而易见,这样将会造成难以控制的错误。

  • 建议如下的方式:

    foo = 1;
    console.log(foo);
    function MyObj() {
    this.foo = 1;
    }
    MyObj.func1 = function () {
    if (this.foo == 1) {
    // ...
    }
    }
  • 不建议如下的方式:

    this.foo = 1; // Noncompliant
    console.log(this.foo); // Noncompliant
    function MyObj() {
    this.foo = 1; // Compliant
    }
    MyObj.func1 = function () {
    if (this.foo == 1) { // Compliant
    // ...
    }
    }

15. 相同的名字不能在相同的作用域内重复声明

  • 等级:Major
  • 原因:不能在一个作用域内使用相同的名子声明变量或函数。这不但会降低代码可读性,而且会导致不必要的错误。

  • 建议如下的方式:

    var fun = function fun() {
    }
    * 不建议如下的方式:
    var fun;
    function fun() {
    }

16. 变量声明时一定要带VAR

  • 等级:Major
  • 原因:JavaScript变量的作用域很难掌握准确。如果存在全局变量会让这种情况变得更糟。

  • 建议如下的方式:

    function f() {
    var i = 1;
    for (var j = 0; j < array.length; j++) {
    // ...
    }
    }
  • 不建议如下的方式:

    function f() {
    i = 1; // Noncompliant; i is global
    for (j = 0; j < array.length; j++) { // Noncompliant; j is global now too
    // ...
    }
    }

17. 变量需要在使用前声明

  • 等级:Major
  • 原因:JavaScript困扰开发人员的最大问题就是作用域。主要的原因是虽然JavaScript看起来像是类似C语言的。但是实际并不是。C语言家族有明显的的作用域标志,它们是通过块来控制的,比如if块,你可以在里边建立新的变量,这样并不会影响块以外的作用域,而JavaScript却不可以。为了尽量避免作用域的困扰,在变量使用前一定要先声明。

  • 建议如下的方式:

    var x = 1;
    function fun() {
    print(x);
    if (something) {
    x = 42;
    }
    }
    fun(); // Print "1"
  • 不建议如下的方式:

    var x = 1;
    function fun() {
    alert(x); // Noncompliant as x is declared later in the same scope
    if (something) {
    var x = 42; // Declaration in function scope (not block scope!) shadowsglobal variable
    }
    }
    fun(); // Unexpectedly alerts "undefined" instead of "1"

18. 变量不能被覆盖

  • 等级:Major
  • 原因:覆盖一个在外域的变量会降低代码可读性和可维护性。更有甚者,会引入错误。

  • 建议如下的方式:

    show: function (point, element) {
    if (!this.drops.length) return;
    var drop,
    affected = [
    ];
    this.drops.each(function (aDrop) {
    if (Droppables.isAffected(point, element, aDrop))
    affected.push(aDrop);
    });
  • 不建议如下的方式:

    show: function (point, element) {
    if (!this.drops.length) return;
    var drop,
    affected = [
    ];
    this.drops.each(function (drop) { // Non-Compliant; defines a new 'drop' parameter
    if (Droppables.isAffected(point, element, drop))
    affected.push(drop);
    });

19. 基本类型定义时不能使用包装对象的方式

  • 等级:Major
  • 原因:使用基本类型包装的对象定义变量是没有意义的。

  • 建议如下的方式:

    var x = false;
    if (x) {
    alert('hi');
    }
  • 不建议如下的方式:

    var x = new Boolean(false);
    if (x) {
    alert('hi'); // Shows 'hi'.
    }

安全相关——7条

1. .ALERT()函数不应该被使用

  • 等级:Info
  • 原因:在开发的过程中,会使用alert()进行debug,但是发布的应用中,这种弹出方式可能会给攻击者泄露敏感信息。

  • 不建议如下使用方式:

    if (unexpectedCondition)
    {
    alert('Unexpected Condition');
    }

2. 代码不应该动态注入执行,以防止出现EVAL注入问题

  • 等级:Critical
  • 原因:eval是在运行的时候执行任意代码的函数,一般来说,用eval函数是很危险的,因为它可以执行任意的代码,如果经过必须使用该函数,则要特别注意该函数处理的任何用户输入数据。

  • 不建议如下使用方式:

    eval(code_to_be_dynamically_executed)
    

3. CONSOLE LOGGING不应该被使用

  • 等级:Info
  • 原因:Debug信息在开发过程中很有用,但是在发布的版本中,特别是客户端保留Debug信息,会造成敏感信息泄露,使浏览器运行缓慢,甚至是浏览器进程崩溃错误。

  • 不建议如下使用方式:

    console.log(password_entered);
    

4. 跨文档消息应该被限制

  • 等级:Critical
  • 原因:HTML5引入了一个在跨域页面之间通讯的方法,为了降低向目标域以及未知域中传递敏感消息的危险,每次调用Window.postmessage方法的时候都须多加注意,不应该使用通配符*。

  • 不建议如下的使用方式:

    var myWindow = document.getElementById('myIFrame').contentWindow;
    myWindow.postMessage(message, '*'); // Noncompliant; how do you know what you loaded in 'myIFrame' is still there?

5. DEBUGGER语句不应该被使用

  • 等级:Critical
  • 原因:Debugger语句可以在程序的任何地方声明来暂停程序执行。利用debugger语句就像在代码中加了一个断点一样。在发布的代码中,任何debugger语句都必须被移除。

  • 不建议如下的使用方式:

    for (i = 1; i < 5; i++) {
    // Print i to the Output window.
    Debug.write('loop index is ' + i);
    // Wait for user to resume.
    debugger;
    }
  • 建议如下的使用方式:

    for (i = 1; i < 5; i++) {
    // Print i to the Output window.
    Debug.write('loop index is ' + i);
    }

6. 无用的“IF(TRUE) {...}” 以及“IF(FALSE){...}” 代码块应该被移除

  • 等级:Major
  • 原因:被false包括的代码块可能没有实际用处,被true声明的代码块是冗余的,并且降低了代码的可读性。
  • 不建议如下的使用方式:

    if (true) { // Noncompliant
    doSomething();
    }...if (false) { // Noncompliant
    doSomethingElse();
    }
    if (!options || options === true) {
    doThirdThing();
    }
    // Noncompliant; always true
  • 建议的使用方式:

    doSomething();
    doThirdThing();

7. 不要使用本地数据库,本地数据库,也就是WEB SQL DATABASE,是随着HTML5规范加入的在浏览器端运行的轻量级数据库。

  • 等级:Critical
  • 原因:本地数据库标准在W3C标准中已经不推荐使用,此外,使用本地数据库也会产生相应的安全问题。

  • 不建议如下的使用方式:

    var db = window.openDatabase('myDb', '1.0', 'Personal secrets stored here', 2 * 1024 * 1024); //Noncompliant
    

性能相关----5条

1. 在靠类型选择元素的时候应该利用“[TYPE=...]”

  • 等级:Major
  • 原因:在JQuery中,和type="<element_type>"都可以用来选择元素,但是type="<element_type>"因为利用了本地的DOM querySelectorAll()方法,所以更快一些。

  • 不建议如下的方式:

    var input = $( 'form input:radio' ); // Noncompliant
    
  • 建议如下的方式:

    var input = $( 'form input[type=radio]' ); // Compliant
    

2. 在JQUERY中,查找某个元素的子节点时,如果已知该元素的ID,则应该用FIND方法,这样可以让查询变得更快,使应用相应更加及时。

  • 等级:Major
  • 不建议如下的方式:

    var $productIds = $('#products div.id'); // Noncompliant - a nested query for Sizzle selector engine
    
  • 建议如下的方式:

    var $productIds = $('#products').find('div.id'); // Compliant - #products is already selected by document.getElementById() so only div.id needs to go through Sizzle selector engine
    

3. 不赞成的JQUERY方法不应该被使用

  • 等级:Major
  • 原因:不赞成的方法是将会被取代的方法,并且最终会被移除,下面的方法是不建议被使用的方法 .andSelf() .context .die() .error() jQuery.boxModel jQuery.browser jQuery.sub() jQuery.support .live() .load() .selector .size() .toggle() .unload()

4. 选择结果应该被保存

  • 等级:Major
  • jQuery不会替你缓存元素,如果你选择了你可能还会用到的变量,你应该将选择结果保存在变量中。

  • 不推荐如下的方式:

    $( 'p' ).hide();
    $( 'p' ).show();
  • 推荐如下的方式:

    var paragraph = $( 'p' );
    paragraph.hide();
    paragraph.show();
  • 例外情况:DOM变化时,保存的selections没有更新, 如下:

    var paragraph = $('p');
    // ...
    paragraph = $('p');
  • 触发本条规则的重复值为2

5. 通配选择器不应该被使用

  • 等级:Major
  • 原因:使用通配选择器会使影响性能,使应用变慢,所以应该限制通配选择器的使用。
  • 不建议如下的方式:

    $( '.buttons > *' );  // Noncompliant; extremely expensive
    
  • 建议如下的方式:

    $( '.buttons' ).children(); // Compliant
    

约定规范——10条

1. 注释不应该写在每一行的最后面

  • 等级:Info
  • 原因:关于单行的注释,不建议将注释写在该行代码的最后,为了增加程序的可读性,建议将注释写在代码的前一个空行上。

  • 不建议如下的方式:

    var a1 = b + c; // This is a trailing comment that can be very very long
    
  • 建议如下的方式:

    // This very long comment is better placed before the line of code
    var a2 = b + c;
    当注释只有一个单词的时候,允许注释写在代码的后面,这是一种特例
    doSomething(); //FIXME

2. 每一条声明须要由“;”结尾

  • 等级:Major
  • 原因:虽然在JavaScript中,在声明后面添加“;”不是强制性的,但是省略“;”是一种不值得提倡的做法,在有些情况下可能会引起意想不到的结果。

  • 不建议如下的方式:

    function fun() {
    return
    // Noncompliant. ';' implicitly inserted at end of line
    5
    // Noncompliant. ';' implicitly inserted at end of line
    }
    print(fun()); // prints "undefined", not "5"
  • 建议如下的方式:

    function fun() {
    return 5;
    }
    print(fun());

3. 文件后面应该包含一个空行

  • 等级:Minor
  • 原因:这条规则会使得在利用一些工具,例如Git的时候配合的更好。

  • 建议如下的使用方式:

    class Test {
    }
    \\newline at end of file

4. FUNCTION的名称应该遵从命名规范

  • 等级:Major
  • 原因: 共同遵守一个命名规范是团队合作高效的一个关键点。某些函数命名方式不建议被使用。
  • 不建议如下的方式:

    function DoSomething(){...}
    
  • 建议如下的方式:

    function doSomething(){...}
    
  • 默认的规范正则表达式为:^[a-z][a-zA-Z0-9]*$

5. JQUERY的缓存变量命名应该遵从规范

  • 等级:Major
  • 原因:和第4点相同,JQuery的变量命名也需要符合一定的规范。

  • 默认的命名检查正则表达式为:^\$[a-z][a-zA-Z0-9]*$

6. 一行代码不要太长

  • 等级:Info
  • 原因:如果一行代码太长,阅读起来不利于理解代码的含义,这里一行默认的最大代码长度为80。

7. 一行代码结束后不应该额外的空格

  • 等级:Minor
  • 原因:结尾的空格是无用的,且不应该保留在代码中,在比较不同版本的相同文件时,末尾的空格可能会造成影响。

  • 不建议如下的方式:

    // The following string will error if there is a whitespace after '\'
    var str = "Hello \
    World";

8. 声明STRING类型的变量是需要用单引号

  • 等级:Minor
  • 原因:将字符串用单引号声明而非双引号。

  • 不建议如下的方式:

    var firstParameter = "something";
    
  • 建议如下的方式:

    var firstParameter = 'something';
    

9. 源代码文件应该有足够的注释

  • 等级:Minor
  • 原因:代码注释量必须达到一定的阈值。默认的代码注释量为15%

10. STATEMENTS应该被分成多行

  • 等级:Minor
  • 原因:为了便于阅读,不要将许多statement放在一行

  • 不建议如下的方式:

    if(someCondition) doSomething();
    
  • 建议如下的方式:

    if(someCondition) {
    doSomething();
    }
  • 例外情况:遇到只包含一个statement的匿名函数时例外,如下:

    onEvent(function() { doSomething(); });               // Compliant
    onEvent(function(p) { doSomething(); return p %2 ;}); // Noncompliant

浏览器兼容性问题----2条

1. 命名函数表达式不应该被使用

  • 等级:Major
  • 原因:某些浏览器不支持命名函数表达式,比如IE8

  • 不建议如下的方式:

    f = function fun(){}; // Non-Compliant;  named function expression
    
  • 建议如下的方式:

    fun = function(){}; // Compliant; function expression
    
  • 例外情况:ECMAScript6的generator function不被包含在内,如下:

    function* f() {} // Compliant; generator function.
    

2. 在块中不应该直接使用函数表达式

  • 等级:Major
  • 原因:虽然大多数script引擎支持在块中声明函数,但是它不是ECMAScript5以及其之前版本的标准,且各个浏览器的处理方式是不一致的。如果你的目标浏览器不支持ECMAScript6,那么在块中利用变量定义一个函数表达式。

  • 不建议如下的使用方式:

    if (x) {
    function foo() {}
    }
  • 建议如下的方式:

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

一些建议——8条

1. 控制语句,IF,FOR,WHILE,SWITCH,以及TRY不应该嵌套的太深

  • 等级:Minor
  • 原因:嵌套太深的代码难以阅读,重构以及维护

  • 不建议如下的方式:

    if (condition1) { // Compliant - depth = 1
    /* ... */
    if (condition2) { // Compliant - depth = 2
    /* ... */
    for (inti = 0; i < 10; i++) { // Compliant - depth = 3, not exceeding the limit
    /* ... */
    if (condition4) { // Non-Compliant - depth = 4
    if (condition5) { // Depth = 5, exceeding the limit, but issues are only reported on depth = 4
    /* ... */
    }
    return;
    }
    }
    }
    }
  • 默认触发问题报告的嵌套深度为3.

2. 表达式不应该太复杂

  • 等级:Major
  • 原因:表达式的复杂程度是由&&,||,以及?,ifTrue:ifFalse操作符定义的,一个表达式不应该有超过三个的操作符,以增加表达式的可读性。

  • 默认触发值为3.

3. FUNCTIONS不应该有太多行

  • 等级:Major
  • 原因:一个较大的函数集合了许多功能,这样的函数不可避免的难以理解以及维护。如果超过了阈值,则强烈建议将函数分成定义良好的函数。这些较小的函数不仅便于理解,而且有利于测试。
  • 例外情况:
    这个函数忽略了Immediately Invoked Function Expressions (IIFE),函数被创建或者调用时没有分配名字。如下:

    (function () { // Ignored by this rule
    function open() { // Classic function declaration; not ignored
    // ...
    }
    function read() {
    // ...
    }
    function readlines() {
    // ...
    }
    }) ();
  • 触发此条件的函数的最大行为300

4. 函数不应该有太多的参数

  • 等级:Major
  • 原因: 很长的参数列表意味着一个新的结构需要被创建来包含大量的参数,或者说明这个函数做的事情太多了。
  • 不建议如下的方式:

    function doSomething(param1, param2, param3, param4, param5) {
    ...
    }
  • 建议如下的方式:

    public void doSomething(intparam1, intparam2, intparam3, Stringparam4) {
    ...
    }
  • 触发该问题的参数临界值为7,建议用数组或对象代替多个参数。

5. 循环不应该包括多余一个的BREAK或者CONTINUE语句

  • 等级:Info
  • 原因:限制循环中的break以及continue语句的数量是一个好的编程习惯。一个break或者continue语句在循环中是可以接受的,如果多于一个的话,则要考虑重构代码段。
  • 不建议如下的方式:

    for (var i = 1; i <= 10; i++) { // Noncompliant - 2 continue - one might be tempted to add some logic in between
    if (i % 2 == 0) {
    continue;
    }
    if (i % 3 == 0) {
    continue;
    }
    alert('i = ' + i);
    }

6. 表达式周围无用的括号应该被移除,以避免任何误解

  • 等级:Major
  • 简单说明如下:

    return 3; // Compliant
    return (x); // Non-Compliant
    return (x + 1); // Non-Compliant
    intx = (y / 2 + 1); // Non-Compliant
    inty = (4 + X) * y; // Compliant

7. 没有用的本地变量应该被移除

  • 等级:Major
  • 原因:如果一个本地的变量被声明而没有被使用,它应该被移除,这样会提高代码维护的效率。

  • 不建议如下的方式:

    function numberOfMinutes(hours) {
    var seconds = 0; // seconds is never used
    return hours * 60;
    }
  • 建议如下的方式:

    function numberOfMinutes(hours) {
    return hours * 60;
    }

8. ARGUMENTS.CALLER和ARGUMENTS.CALLEE不应该被使用

  • 等级:Major
  • 原因:这两个函数在最新的Javascript版本中不建议被使用,可能会对优化造成影响。在ECMAScript5中,这两个函数在strict模式下都被禁止使用。

  • 不建议如下的方式:

    function whoCalled() {
    if (arguments.caller == null) //Noncompliant
    console.log('I was called from the global scope.');
    else
    console.log(arguments.caller + ' called me!'); // Noncompliant
    console.log(whoCalled.caller); // Noncompliant
    console.log(whoCalled.arguments); // Noncompliant
    }

Bad-practice——6条

1. 多行的STRING变量不应该使用\

  • 等级:Major
  • 原因:虽然不同的script引擎可以识别多行的string变量(用\方式),但是这种形式没有被规定在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 have got an error and all the extraneous whitespace is \
    just gravy. Have a nice day.'; // Noncompliant
  • 建议如下的方式:

    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 have got an error and all the extraneous whitespace is ' +
    'just gravy. Have a nice day.';

2. 下面这种情况,应该用WHILE代替FOR循环

  • 等级:Major
  • 原因:当for循环中之定义了状态时应该用while循环代替

  • 不建议如下的方式:

    for (; condition; ) { /*...*/
    }
  • 建议如下的方式:

    while (condition) { /*...*/
    }

3. 可折叠的IF语句应该被合并

  • 等级:Major
  • 原因:合并可折叠的if语句,从而增加代码的可读性

  • 不建议如下的方式:

    if (x != undefined) {
    if (x === 2) {
    // ...
    }
    }
  • 建议如下的方式:

    if (x != undefined && x === 2) {
    // ...
    }

4. 在表达式中,BOOLEAN(TRUE和FALSE)值不应该出现

  • 等级:Minor
  • 原因:移除状况表达式中的true以及false。状态表达式中出现false以及true是没有必要的。
  • 不建议如下的方式:

    if (booleanVariable == true) { /* ... */
    }
    if (booleanVariable != true) { /* ... */
    }
    if (booleanVariable || false) { /* ... */
    }
    doSomething(!false);
  • 建议如下的方式:

    if (booleanVariable) { /* ... */
    }
    if (!booleanVariable) { /* ... */
    }
    if (booleanVariable) { /* ... */
    }
    doSomething(true);
  • 例外情况:如果文字的布尔值出现在恒等运算符中则被忽略,如下:

    (=== and !==)
    

5. 返回BOOLEAN类型的表达式不应该被放在IF-THEN-ELSE语句中

  • 不建议如下的方式:

    if (expression) {
    return true;
    } else {
    return false;
    }
  • 建议如下的方式:

    return expression;
    return !!expression;

6. 结尾的逗号不应该被使用

  • 等级:Blocker
  • 原因:在某些浏览器中会出现错误,如IE
  • 不建议被使用的方式:

    var settings = {
    'foo': oof,
    'bar': rab, // Noncompliant - trailing comma
    };
  • 建议的方式:

    var settings = {
    'foo': oof,
    'bar': rab
    };

其它----2条

1. ”TODO”标签不能出现

  • 等级:info
  • 原因:该标签是一个标记开发人员将来将要在此处实现某些代码的标志。有时开发人员会忘记这事,需要对开发人员作出提醒。

  • 不建议如下的方式:

    function doSomething() {
    // TODO
    }

2. ”FIXME”标签不能出现

  • 等级:Major
  • 原因:FIXME是开发人员对出现错误的代码进行的标记,有时开发人员可能会忘记,需要进行一下提醒。

    function divide(numerator, denominator) {
    return numerator / denominator; // FIXME denominator value might be 0
    }

js编写规范的更多相关文章

  1. 前端、HTML+CSS+JS编写规范(终极版)

    HTMLCSS文档规范 HTML和CSS文档必须采用UTF-8编码格式: HTML文档必须使用HTML5的标准文档格式: HTMLCSS编写规范 HTML和CSS的标签.属性.类名.ID都必须使用小写 ...

  2. Node.js编写CLI的实践

    导语:通常而言,Node.js的应用场景有前后端分离.海量web页面渲染服务.命令行工具和桌面端应用等等.本篇文章选取CLI(Command Line Tools)这子领域,来谈谈Node.js编写C ...

  3. 个人css编写规范

    前言:最近在做微信小程序,因为公司小,就我一个人弄前端的东西,js和页面都是我来弄,结果那天后台的人看到我的js代码,说我的代码写得不规范,函数什么的都很乱,弄得我羞愧难当,幸亏没看我的css,其实我 ...

  4. JavaScript必备:Google发布的JS代码规范(转)

    [翻译]关于Google发布的JS代码规范,你需要了解什么? 翻译 | WhiteYin 译文 | https://github.com/WhiteYin/translation/issues/10 ...

  5. 1-html基本结构与编写规范

    <!DOCTYPE html> <html> <!-- #前端开发系统化学习教程, #包括html.css.pc端及移动端布局技巧.javascript. #jquery ...

  6. 谷歌与Airbnb的JS代码规范

    谷歌JS代码规范 规范代码原因:代码规范是为了保持源代码编写模式一致,便于维护代码,可读性高. 1.使用空格代替tab 规范随后指出应该使用2个,而不是4个空格带实现缩进.(除了每一行的终止符序列,A ...

  7. JS模块规范:AMD,CMD,CommonJS

    浅析JS模块规范 随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比 ...

  8. 前端规范之JS代码规范(ESLint + Prettier)

    代码规范是软件开发领域经久不衰的话题,几乎所有工程师在开发过程中都会遇到或思考过这一问题.而随着前端应用的大型化和复杂化,越来越多的前端团队也开始重视代码规范.同样,前段时间,笔者所在的团队也开展了一 ...

  9. Postman接口测试脚本编写规范

    Postman接口测试脚本编写规范 1.前言 2.名词解释 3.接口测试脚本规范 3.1接口测试脚本编写的规范 3.2 Postman使用规范 4.单个接口测试 5.整个流程的开发过程 1.前言 本规 ...

随机推荐

  1. SMART Goals

    Once you have planned your project, turn your attention to developing several goals that will enable ...

  2. iOS: 使用KVO监听控制器中数组的变化

    一.介绍: KVO是一种能动态监听到属性值的改变的方式,使用场景非常广泛,这里我只讲如何监听控制器ViewController中数组的变化. 二.了解: 首先我们应该知道KVO是不能直接监听控制器Vi ...

  3. 在Windows上安装PyCUDA跟Theano

    http://www.myexception.cn/cuda/1904274.html

  4. eclipse启动tomcat错误:A Java Exception has occurred(转)

    在tomcat bin目录下执行startup.bat可以正常启动,但在eclipse下安装了tomcat插件并且配置tomcat路径后启动且报错:A Java Exception has occur ...

  5. 浅谈负载均衡SLB、CLB和综合应用

    SLB     服务器负载均衡(Server Load Balancing),可以看作HSRP(热备份路由器协议)的扩展,实现多个服务器之间的负载均衡.     虚拟服务器代表的是多个真实服务器的群集 ...

  6. Spring Boot 2 Swagger2

    本文将介绍RESTful API的重磅好伙伴Swagger2,它可以轻松的整合到Spring Boot中,并与Spring MVC程序配合组织出强大RESTful API文档. 它既可以减少我们创建文 ...

  7. [PCL]NDT点云匹配方法

    测试NDT方法的Demo,http://pointclouds.org/documentation/tutorials/normal_distributions_transform.php#norma ...

  8. 关于 0xCCCCCCCC

    http://xingyunbaijunwei.blog.163.com/blog/static/76538067201281793111474/ http://stackoverflow.com/q ...

  9. cocos2dx 3.x(Button传统按钮)

    // // ATTLoagingScene.hpp // ATT // // Created by work on 16/10/13. // // #ifndef ATTLoagingScene_hp ...

  10. thttpd增加gzip压缩响应报文体功能,以减少传输数据量

    thttpd thttpd是一个非常小巧的轻量级web server,它非常非常简单,仅仅提供了HTTP/1.1和简单的CGI支持,在其官方网站上有一个与其他web server(如Apache, Z ...