應該使用“ === ”和“!==”代替“ ==”和“!=”
在==
與!=
比較值之前,執行類型強制。這很糟糕,因爲它可能掩蓋類型錯誤。
例如,它的計算結果' \t\r\n' == 0
返回爲true
。
“ [type = …]”應用於按類型選擇元素
雖然:<element_type>
和[type="<element_type>"]
都可以在jQuery中用於按元素類型選擇元素,但[type="<element_type>"]
速度要快得多,因爲它可以利用querySelectorAll()
現代瀏覽器中的本機DOM 方法。
使用以下選擇器時,此規則會引起問題:
- :checkbox
- :file
- :image
- :password
- :radio
- :reset
- :text
不兼容的代碼示例:
var input = $(“ form input:radio”); //不符合規定
兼容解決方案:
var input = $(“ form input [type = radio]”); //符合
不推薦使用,該規則已棄用,最終將被刪除。
不應使用“ alert(…)”
alert(...)
以及confirm(...)
和prompt(...)
可以在開發過程中調試非常有用,但在生產模式這種彈出的可能暴露敏感信息給攻擊者,不應該被顯示。
不兼容的代碼示例:
if(unexpectedCondition){
alert(“意外情況”);
}
“arguments” 不應直接訪問
JavaScript的神奇之處在於,你可以將參數傳遞給未聲明參數的函數,另一方面,也可以在no-args內使用這些傳入的參數function。
如果你不想顯式命名參數,請使用...
語法指定期望可變數量的參數。然後在函數內部,你將要處理一類數組,而不是類似數組的結構。
不兼容的代碼示例:
function concatenate() {
let args = Array.prototype.slice.call(arguments); // Noncompliant
return args.join(', ');
}
function doSomething(isTrue) {
var args = Array.prototype.slice.call(arguments, 1); // Noncompliant
if (!isTrue) {
for (var arg of args) {
...
}
}
兼容解決方案:
function concatenate(...args) {
return args.join(', ');
}
function doSomething(isTrue, ...values) {
if (!isTrue) {
for (var value of values) {
...
}
}
}
不應使用“ arguments.caller”和“ arguments.callee”
arguments.caller
和arguments.callee做
了不少優化,不可能讓他們在JavaScript中的最新版本中不建議使用。實際上,strict根據文檔,EcmaScript 5禁止在模式下同時使用兩者:
嚴格模式功能的參數對象定義了名爲“ caller”
和“ callee”
的不可配置的訪問器屬性,這些屬性在訪問時引發TypeError異常
。
不兼容的代碼示例:
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
“ await”不應冗餘使用
一個async函數總是包裹在一個返回值Promise,return await的使用是多餘的。
不兼容的代碼示例:
async function foo() {
// ...
}
async function bar() {
// ...
return await foo(); // Noncompliant
}
兼容解決方案:
async function foo() {
// ...
}
async function bar() {
// ...
return foo();
}
“ catch”子句的作用不僅僅在於重新拋出
一個catch子句只會重新拋出捕獲到的異常,其效果與完全省略catch並讓它自動彈出的效果相同,但會產生更多的代碼,而且還會增加維護人員的工作量。
此類子句應被消除或使用適當的邏輯填充。
不兼容的代碼示例:
try {
doSomething();
} catch (ex) { // Noncompliant
throw ex;
}
兼容解決方案:
try {
doSomething();
} catch (ex) {
console.err(ex);
throw ex;
}
不應使用“continue”
continue是非結構化的控制流語句。它使代碼的可測試性,可讀性和可維護性降低。if應該使用結構化的控制流語句,例如:
不兼容的代碼示例:
for (i = 0; i < 10; i++) {
if (i == 5) {
continue; /* Noncompliant */
}
alert("i = " + i);
}
兼容解決方案:
for (i = 0; i < 10; i++) {
if (i != 5) { /* Compliant */
alert("i = " + i);
}
}
“default”子句應寫在最後
switch可以default出於各種原因而包含一個子句:處理意外值,以表明所有情況都經過適當考慮。
出於可讀性考慮,爲了幫助開發人員快速找到switch語句的默認行爲,建議將default子句放在 語句的末尾switch。如果default子句不是的第一個或最後一個switch案例,則此規則會引起問題。
不兼容的代碼示例:
switch (param) {
case 0:
doSomething();
break;
default: // default clause should be the first or last one
error();
break;
case 1:
doSomethingElse();
break;
}
兼容解決方案:
switch (param) {
case 0:
doSomething();
break;
case 1:
doSomethingElse();
break;
default:
error();
break;
}
“delete”應僅與對象屬性一起使用
delete運算符的語義有些棘手,並且只能可靠地用於從對象中刪除屬性。將其他任何內容傳遞給它,你可能會或可能不會獲得預期的結果。
不兼容的代碼示例:
var x = 1;
delete x; // Noncompliant
function foo(){
..
}
delete foo; // Noncompliant
兼容解決方案:
var obj = {
x:1,
foo: function(){
...
}
};
delete obj.x;
delete obj.foo;
“delete”不應在數組上使用
delete可用於從任何對象中刪除一個屬性。數組是對象,因此delete也可以在此處使用運算符,但如果是,數組中將留下一個洞,因爲索引/鍵不會移動以反映刪除。
刪除某個索引處的元素的正確方法是:
- Array.prototype.splice -從數組中添加/刪除元素
- Array.prototype.pop -從數組末尾添加/刪除元素
- Array.prototype.shift -從數組的開頭添加/刪除元素
不兼容的代碼示例:
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
兼容解決方案:
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'
“ for … in”循環應先對屬性進行過濾,然後再對其進行操作
for…in語句使你可以遍歷對象的所有屬性的名稱。屬性列表包括通過原型鏈繼承的所有那些屬性。當對數據屬性感興趣時,這具有提供功能的副作用。不考慮這一點的程序可能會失敗。
因此,每個for…in語句的主體都應該包含在一個if過濾器中,該過濾器將作用於哪些屬性。它可以選擇特定類型或值範圍,也可以排除函數,也可以排除原型中的屬性。
不兼容的代碼示例:
for (name in object) {
doSomething(name); // Noncompliant
}
兼容解決方案:
for (name in object) {
if (object.hasOwnProperty(name)) {
doSomething(name);
}
}
“ indexOf”檢查不應爲正數
大多數針對indexO
f字符串或數組的調用檢查都會將其與-1比較,因爲0是有效索引。任何尋找值> 0的檢查都會忽略第一個元素,這很可能是一個錯誤。如果僅檢查字符串的存在,請考慮includes
改爲使用 。在使用includes
方法之前 ,請確保你的瀏覽器版本支持該方法。
不兼容的代碼示例:
var color = "blue";
var name = "ishmael";
var number = 123;
var arr = [color, name];
if (arr.indexOf("blue") > 0) { // Noncompliant
// ...
}
if (name.indexOf("ish") > 0) { // Noncompliant
// ...
}
兼容解決方案:
var color = "blue";
var name = "ishmael";
var number = 123;
var arr = [color, name];
if (arr.indexOf("blue") >= 0) {
// ...
}
if (name.includes("ish")) {
// ...
}
比較中不應使用“ NaN”
NaN不等於任何東西,甚至不等於任何東西。針對進行相等性或不相等性測試NaN將產生可預測的結果,但可能不是您想要的結果。
相反,查看變量是否等於的最佳方法NaN是使用Number.isNaN()ES2015
以來的,或者使用(也許是違反直覺的)將其與自身進行比較。從那時起
NaN ! == NaN
,a ! == a
你知道它必須相等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
}
兼容解決方案:
if (Number.isNaN(a)) {
console.log("a is not a number");
}
if (!Number.isNaN(a)) {
console.log("a is not NaN");
}
“strict”模式應謹慎使用
即使強制執行JavaScript嚴格模式可能是一個好習慣,但這樣做可能會導致尚不支持JavaScript嚴格模式的瀏覽器出現意外行爲。因此,應謹慎使用此功能,並充分了解不支持此功能的瀏覽器的潛在後果。
不兼容的代碼示例:
function strict() {
'use strict';
應該適當調用“ super()”
在某些情況下super()必須調用,而在某些情況下super()則不能調用。
基本規則是:非派生類中的構造函數無法調用super();派生類中的構造函數必須調用 super()。
此外:
-
super()必須先調用,然後才能使用
this
andsuper
關鍵字。 -
super()必須使用與基類的構造函數相同數量的參數來調用。
-
super()只能在構造函數中調用-不能在任何其他方法中調用。
-
super()不能在同一構造函數中多次調用。
不兼容的代碼示例:
class Dog extends Animal {
constructor(name) {
super();
this.name = name;
super(); // Noncompliant
super.doSomething();
}
}
兼容解決方案:
class Dog extends Animal {
constructor(name) {
super();
this.name = name;
super.doSomething();
}
}
“ switch”語句不應嵌套
嵌套switch結構很難理解,因爲你很容易將內部的情況混淆switch爲屬於外部的語句。因此,switch應避免使用嵌套語句。
具體來說,你應該對代碼進行結構化,以避免需要嵌套switch語句,但是如果不能,則請考慮將內部結構switch移至另一個函數。
不兼容的代碼示例:
function foo(n, m) {
switch (n) {
case 0:
switch (m) { // Noncompliant; nested switch
// ...
}
case 1:
// ...
default:
// ...
}
}
兼容解決方案:
function foo(n, m) {
switch (n) {
case 0:
bar(m);
case 1:
// ...
default:
// ...
}
}
function bar(m) {
switch(m) {
// ...
}
}