js編寫規范


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 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM