JavaScript語言規范-來自Google

既然要寫JS,必須要遵循一定的編程規范吧。以下是來自Google的JS語言規范,直接翻譯過來的(可參考英文原版)。

 1,變量:大部分情況下請使用var聲明
  如果不顯示使用var,這個變量就會被附著在全局上下文中,可能引起重名的沖突。而且,如果不使用var聲明,也 很難分辨這個變量的作用域(如:可能附著在Document或Window對象上,也可能附著在局部變量上)。所以,大部 分情況下使用var來聲明變量。
  當然,如果申請一個隻屬於某一個“類”的變量,則不要使用var。如jQuery(版本為1.6.4)中為jQuery的第41 行,要為jQuery對象增加屬性,所以不能使用var來聲明。
 2,常量:使用NAME_LIKE_THIS的命名方法,適當使用@const,不要使用const關鍵詞。
  對於簡單的“非引用”類型,這種命名方法足矣。如:

Js代碼 
<span style="font-size: medium;">/**
* The number of seconds in a minute.
* @type {number}
*/ 
goog.example.SECONDS_IN_A_MINUTE = 60;</span> 
 

  對於“引用”類型,使用@const註解。如:

Js代碼 
<span style="font-size: medium;">/**
 * The number of seconds in each of the given units.
 * @type {Object.<number>}
 * @const
 */ 
goog.example.SECONDS_TABLE = { 
  minute: 60, 
  hour: 60 * 60 
  day: 60 * 60 * 24 
}</span> 

   這樣可以保證編譯器保證常量的意義。
  至於const關鍵字,由於IE不支持,所以不要使用。
 3,分號:使用之。
  不顯式使用分號,有可能導致難以察覺的問題。特別是如下幾處:

Js代碼 
<span style="font-size: medium;">//1. 
MyClass.prototype.myMethod = function(){ 
    return 42; 
}  // 這裡沒有分號 
(function(){ 
    //初始化一些變量,作用域為該匿名函數 
})(); 
var x = { 
    'i':1, 
    'j':2 
}  //這裡沒有分號 
 
//2. 
[normalVersion,ffVersion][isIE](); 
 
var THINGS_TO_EAT = [apples,oysters,sprayOnCheese] //沒有分號 
 
//3. 
-1 == resultOfOperation() || die(); 
</span> 

   發生什麼呢?
  第一處:JS錯誤-首先,返回24的函數會執行,因為後面有一個圓括號,而且參數是一個函數;然後返回值42 被調用,出錯。
  第二處:執行的時候你非常可能得到一個“no such property in undefined”的錯誤,因為實際上是在執行 x[ffVersion][isIE]()這個函數。
  第三處:函數die隻有在resultOfOperation()為NaN,THINGS_TO_EAT會被賦值成die()的返回值。

  為什麼呢?
  JS的語法要求一個語句要以分號結尾,除非能安全的推斷出分號的位置。在上述例子中,函數聲明,對象聲明, 數組等被用在一個語句中。類似如“}”,“]”的符號不足以證明語句的結束。如果下一個字符是運算符或者"{","[",則 JS會認為語句沒有結束。

  這寫錯誤令人詫異,所以確保賦值語句以分號結尾。

 4,嵌套函數:可以使用
  嵌套函數非常有用,比如在創建持續任務或者隱藏工具函數的時候。不用擔心,使用之。

 5,在語言塊中聲明函數:不要使用!
  不要寫如下代碼:

Js代碼 
<span style="font-size: medium;">if(x){ 
    function ff(){} 
}</span> 

   盡管大多數腳本引擎支持這種函數聲明的方式,但是這並不是ECMAScript標準裡面的。ECMAScript隻支持在 根語句聲明函數。如果需要,可以使用變量來保存這個函數。如下:

Js代碼 
<span style="font-size: medium;">if(x){ 
    var ff = function(){} 
}</span> 

  
 6,異常:可以使用
  如果不是從0開始寫,那麼基本上避免不瞭使用異常,如使用程序開發框架的時候。

 7,自定義異常:可以使用
  沒有自定義異常,那麼一個函數既可以返回正常值,又可以返回一個錯誤信息,這令人費解。不大優雅的解決方 法包括返回執行錯誤信息的引用類型和返回包含潛在錯誤的對象。這些可以說是比較古老的異常處理方法。所以,在 合適的情況下可以使用自定義異常。

 8,標準特性:使用標準特性而不是使用非標準的
  為瞭最大化的實現可移植和兼容。比如使用string.charAt(4),而不是使用string[4];訪問元素要使用DOM函 數,而不是使用某個專屬於一個工程的簡寫。

 9,為原始類型包裝:不要使用!
  沒有必要為原始類型包裝,而且包裝還很容易出錯,如下:

Js代碼 
<span style="font-size: medium;">var x = new Boolean(false); 
if(x){ 
    alert('hi');//會執行 
}</span> 

  不要這樣做!
  然而,類型轉換還是可以的。

Js代碼 
<span style="font-size: medium;">var x = Boolean(0); 
if(x){ 
    alert('hi');//不執行 

typeof Boolean(0) == 'boolean'; 
typeof new Boolean(0) == 'object';</span> 

   這個特點在將對象轉型成number,string,boolean的時候特別有用。

 10,多級原型層次:不建議使用
  多級原型層次可以用來實現繼承。多級原型很難維護。
  (這個本人保留意見)
 11,方法定義:Foo.prototype.bar = function(){};
  盡管有好幾種方式將方法和屬性綁定到一個類,最好的還是這種。

 12,閉包:可以使用,但是要小心!
  閉包也許是JS最有用的特點,或許也是最被濫用的特性。
  但是,要記住,閉包持有對它的關閉范圍的引用。如果將一個閉包賦值給DOM元素,則可能導致循環引用,從 而引起內存泄露,如:

Js代碼 
<span style="font-size: medium;">function foo(element,a,b){ 
    element.onclick = function(){ /* 使用a和b */ 
}</span> 

   函數本身的閉包引用瞭element,a,和b,即使從來沒有使用到element;因為element也保存瞭指向該閉 包的引用,所以形成瞭一個環,不能被GC回收。在這種情況下,可以這樣:

Js代碼 
<span style="font-size: medium;">function foo(element,a,b){ 
    element.onclick = bar(a,b); 

function bar(a,b){ 
    return function(){/* 使用a和b*/} 
}</span> 
 

 13,eval():隻用於反序列化
  eval()會造成令人困惑的語義,而且如果包含用戶輸入的字符串的時候也很危險。通常會有更好的方法來寫這種需求的代碼,所以通常不 用。但是,eval使得反序列化非常簡單,所以可以接受。
  反序列化是將一系列的字符轉換成內存的數據結構的過程。例如,你可能將下面的對象寫到一個文件中去:

Js代碼 
<span style="font-size: medium;">users = [ 
    {}, 
    {}, 
    … 
];</span> 

   要將這個對象讀到內存中,就可以使用eval。
  類似的,eval也可以簡化解碼RPC返回值的任務。如:

Js代碼 
<span style="font-size: medium;">var userOnline = false; 
var user = 'nusrat'; 
var xmlhttp = new XMLHttpRequest(); 
xmlhttp.open('GET', 'https://chat.google.com/isUserOnline?user=' + user, false); 
xmlhttp.send(''); 
// Server returns: 
// userOnline = true; 
if (xmlhttp.status == 200) { 
  eval(xmlhttp.responseText); 

// userOnline is now true.</span> 


 14,with(){}:不要使用!
  使用with會使代碼更有迷惑性。因為with裡面的對象可能會有和局部變量沖突的屬性,所以可能會導致程序的原 意完全變化。例如:

Js代碼 
<span style="font-size: medium;">with(foo){ 
    var x = 3; 
    return x; 
}</span> 

  局部變量x可能與foo的屬性沖突,甚至如果foo的那個屬性有setter,還會導致其他的代碼去執行。所以,不要使 用with!

 15,this:隻用在構造函數,方法,和構建閉包的時候
  使用this容易使人產生疑惑。this可以指向全局對象(window),可以指向調用者,可以指向DOM節點,可以 指向新建的對象,可以指向別的對象(如果方法是用call或者apply調用的)。
  因為this很容易出錯,所以限制適用於以下情況:

構造函數
對象的方法(包括創建閉包)
 16,for-in 循環
  for-in循環經常被錯誤的用於遍歷Array中的元素。錯誤原因在於並不隻是遍歷瞭從0到length-1的元素,而且 還遍歷瞭原型鏈。以下是幾個經常出錯的:
Js代碼 
<span style="font-size: medium;">function printArray(arr) { 
  for (var key in arr) { 
    print(arr[key]); 
  } 

 
printArray([0,1,2,3]);  // This works. 
 
var a = new Array(10); 
printArray(a);  // This is wrong. 
 
a = document.getElementsByTagName('*'); 
printArray(a);  // This is wrong. 
 
a = [0,1,2,3]; 
a.buhu = 'wine'; 
printArray(a);  // This is wrong again. 
 
a = new Array; 
a[3] = 3; 
printArray(a);  // This is wrong again.</span> 
   所以,要使用普通的遍歷。

 17,數組:不要將數組作為map,哈希,聯合的數組
  數組不允許使用非數字的索引,如果需要非數字的索引,可以使用Object。Array可以,是因為Array繼承自 Object。


 18,多行字符串:不要使用
  不要這樣:

Js代碼 
<span style="font-size: medium;">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\'ve got an error and all the extraneous whitespace is \ 
                just gravy.  Have a nice day.';</span> 

   每一行前面的空格在編譯的時候不能被安全的跳過;\後面的空格也可能導致莫名其妙的錯誤;而且,這種語法在 ECMAScript中也是不支持的。
  使用字符串相加即可:

Js代碼 
<span style="font-size: medium;">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\'ve got an error and all the extraneous whitespace is ' + 
    'just gravy.  Have a nice day.';</span> 
 

 19,字面數組和對象:建議使用
  通常使用字面數組和對象來代替構造器。
  Array構造器會因為參數不當而出錯。

Js代碼 
<span style="font-size: medium;">// Length is 3. 
var a1 = new Array(x1, x2, x3); 
 
// Length is 2. 
var a2 = new Array(x1, x2); 
 
// If x1 is a number and it is a natural number the length will be x1. 
// If x1 is a number but not a natural number this will throw an exception. 
// Otherwise the array will have one element with x1 as its value. 
var a3 = new Array(x1); 
 
// Length is 0. 
var a4 = new Array();</span> 

  因為這個原因,如果有人更改代碼傳瞭一個參數進去,而不是兩個參數,代碼可能會背離原意。
  為瞭避免這種情況,這樣:
Js代碼 
<span style="font-size: medium;">var a = [x1, x2, x3]; 
var a2 = [x1, x2]; 
var a3 = [x1]; 
var a4 = [];</span> 
    Object的構造器雖然沒有這個問題,但是為瞭可讀性和連貫性,建議使用字面對象。如:

Js代碼 
<span style="font-size: medium;">var o = {}; 
 
var o2 = { 
  a: 0, 
  b: 1, 
  c: 2, 
  'strange key': 3 
};</span> 


 20,更改內置對象的prototype:禁止!
  更改內置對象的原型是被嚴厲禁止的。

作者“技術愛好者”
 

發佈留言