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 }