交了這麼多年JavaScript學費,你掌握了多少(第一期)

應該使用“ === ”和“!==”代替“ ==”和“!=”

==!=比較值之前,執行類型強制。這很糟糕,因爲它可能掩蓋類型錯誤。

例如,它的計算結果' \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.callerarguments.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”檢查不應爲正數

大多數針對indexOf字符串或數組的調用檢查都會將其與-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 ! == NaNa ! == 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 and super關鍵字。

  • 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) {
    // ...
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章