CoffeeScript 編碼風格指南(譯)

這份指南闡述了一些 CoffeeScript 的最佳實踐和編碼慣例。javascript

這份指南是社羣驅動的,很是鼓勵你們來貢獻內容。html

請注意這仍是一份正在完善的指南:仍有不少地方能夠改進,有些已制定的準則也不必定是社區慣用的(基於此,在適當的狀況下,這些有待斟酌的準則將有可能被修改或刪除。)java

靈感

本指南中的不少細節受到了幾份現有的風格指南和其餘資源的啓發。特別是:python

目錄

代碼佈局(Code Layout)

Tab 仍是 空格?(Tabs or Spaces?)

只用 空格,每級縮進均爲 2 個空格。切勿混用 Tab 和空格。git

最大行寬(Maximum Line Length)

限制每行最多 79 個字符。github

空行(Blank Lines)

頂級函數和類的定義用一個空行分開。數組

類內部的函數定義也用一個空行分開。ruby

對於每一個函數體內,只在爲了提升可讀性的狀況下才使用一個空行(例如:爲了達到劃分邏輯的目的)。less

結尾空白(Trailing Whitespace)

不要在任何一行保留行尾空白。ide

可選的逗號(Optional Commas)

當對象(或數組)的屬性(或元素)做爲單獨一行列出時,避免在換行符前使用逗號。以下:

# 好
foo = [
  'some'
  'string'
  'values'
]
bar:
  label: 'test'
  value: 87

# 差
foo = [
  'some',
  'string',
  'values'
]
bar:
  label: 'test',
  value: 87

編碼(Encoding)

UTF-8 是首選的源文件編碼。

模塊導入(Module Imports)

若是須要導入模塊 (CommonJS 模塊,AMD,等等.), require 語句應該單獨做爲一行。以下:

require 'lib/setup'
Backbone = require 'backbone'

這些語句應該按如下順序去分組:

  1. 標準庫的導入 (若是標準庫存在)
  2. 第三方庫的導入
  3. 本地導入 (導入這個應用程序的或庫的具體依賴)

表達式和語句中的空白(Whitespace in Expressions and Statements)

下列狀況應該避免多餘的空格:

  • 緊貼着圓括號、方括號和大括號內部

    ($ 'body') # 好
       ( $ 'body' ) # 差
  • 緊貼在逗號前

    console.log x, y # 好
       console.log x , y # 差

額外建議:

  • 在下列二元操做符的左右兩邊都保留 一個空格

    • 賦值運算符: =

      • 注意這一樣適用於函數定義中的默認參數

        test: (param = null) -> # 好
        test: (param=null) -> # 差
    • 自增運算符: +=, -=, 等等。

    • 比較運算符: ==, <, >, <=, >=, unless, 等等。
    • 算術運算符: +, -, *, /, 等等。

    • (這些操做符兩邊的空格不要多於一個)

      # 好
         x = 1
         y = 1
         fooBar = 3
      
         # 差
         x      = 1
         y      = 1
         fooBar = 3

註釋(Comments)

若是你修改了一段已有註釋說明的代碼,則也要更新它對應的註釋。(理想狀態是,重構這段代碼直到它不須要註釋說明,而後再把以前的註釋全刪掉。)

註釋的首字母要大寫,除非第一個單詞是以小寫字母開頭的標識符。

若是註釋很短,能夠省略末尾的句號。

塊註釋(Block Comments)

註釋塊一般應用於尾隨其後的一段代碼。

每一行註釋都以 # 加一個空格開頭,並且和被註釋的代碼有相同的縮進層次。

註釋塊內的段落以僅含單個 # 的行分割。

# 這是一個塊註釋。請注意假如這是一段塊註釋,
  # 則它描述的就應該是接下來的這段代碼。
  #
  # 這是塊註釋的第二段。
  # 請注意這段是由上一行帶有 # 號的空行分開的。(P.S. 最好用英文寫註釋)

  init()
  start()
  stop()

行內註釋(Inline Comments)

行內註釋緊貼在被描述的代碼的上一行,若是行內註釋足夠短,則能夠處在同一行行尾(由一個空格隔開)。

全部行內註釋都以 # 加一個空格開頭。

應該限制行內註釋的使用,由於它們的存在一般是一個代碼異味的標誌。

不要給顯而易見的狀況做行內註釋:

# 差
  x = x + 1 # x 自增

然而,行內註釋在某些狀況下是有用的:

# 好
  x = x + 1 # 邊界補足

命名規範(Naming Conventions)

使用 小駝峯命名法 (第一個詞的首字母小寫,後面每一個詞的首字母大寫)來命名全部的變量、方法和對象屬性。

使用 大駝峯命名法 (第一個詞的首字母,以及後面每一個詞的首字母都大寫)來命名全部的類 (在其餘相似的命名法中,這種風格一般也被稱爲 帕斯卡命名法(PascalCase)大寫駝峯命名法(CamelCaps)首字母大寫命名法(CapWords)。)

(CoffeeScript 官方 約定是用駝峯命名法,由於這能夠簡化與 JavaScript 的相互轉化,想了解更多,請看這裏.)

對於常量,單詞所有大寫,用下劃線隔開便可:

CONSTANT_LIKE_THIS

私有函數和私有變量都應該在前面加一個下劃線:

_privateMethod: ->

函數(Functions)

(如下這些準則一樣適用於類中的方法。)

當聲明一個帶參函數時,應在參數列表的右圓括號後空出一個空格:

foo = (arg1, arg2) -> # 好
foo = (arg1, arg2)-> # 差

無參函數不要用圓括號:

bar = -> # 好
bar = () -> # 差

當函數鏈式調用,卻在一行放不下時,則把每一個函數調用都另起一行,且都縮進一級(即在 . 前加兩個空格)。

[1..3]
  .map((x) -> x * x)
  .concat([10..12])
  .filter((x) -> x < 11)
  .reduce((x, y) -> x + y)

當調用函數時,咱們應該爲了提升可讀性而去掉圓括號。請記住,「可讀性」是咱們主觀臆斷的。只有相似下面幾個例子的狀況才被社區認爲是最佳的:

baz 12

brush.ellipse x: 10, y: 20 # 大括號在適當的時候也能夠去掉

foo(4).bar(8)

obj.value(10, 20) / obj.value(20, 10)

print inspect value

new Tag(new Value(a, b), new Arg(c))

有時候你會發現圓括號用來包裹的是函數體(而不是函數的參數)。請看下面的例子(如下簡稱爲「函數體風格」):

($ '#selektor').addClass 'klass'

(foo 4).bar 8

這段代碼會編譯爲:

$('#selektor').addClass 'klass'

foo(4).bar 8

一些習慣鏈式調用的人會巧用「函數體風格」進行單獨初始化:

($ '#selektor').addClass('klass').hide() # 單獨初始化調用
(($ '#selektor').addClass 'klass').hide() # 所有調用

「函數體風格」並不獲得推薦。可是, 當它適應一些特殊的項目需求時,仍是得用它。

字符串(Strings)

用字符串插值代替字符串鏈接符:

"this is an #{adjective} string" # 好
"this is an " + adjective + " string" # 差

最好用單引號 ('') 而不是雙引號 ("") 。除非是插入到另外一段現有的字符串中(相似字符串插值)。

條件判斷(Conditionals)

unless 來代替 if 的否認狀況。

不要用 unless...else, 而用 if...else:

# 好
  if true
    ...
  else
    ...

  # 差
  unless false
    ...
  else
    ...

多行的 if/else 語句應該縮進:

# 好
  if true
    ...
  else
    ...

  # 差
  if true then ...
  else ...

循環和列表解析(Looping and Comprehensions)

儘量的使用列表解析:

# 好
  result = (item.name for item in array)

  # 差
  results = []
  for item in array
    results.push item.name

還能夠過濾結果:

result = (item for item in array when item.name is "test")

遍歷對象的鍵值:

object = one: 1, two: 2
alert("#{key} = #{value}") for key, value of object

擴展本地對象(Extending Native Objects)

不要修改本地對象。

好比,不要給 Array.prototype 引入 Array#forEach

異常(Exceptions)

不要抑制異常拋出。

註解(Annotations)

必要的時候應該寫註解,來指明接下來的代碼塊具體將幹什麼。

註解應緊貼在被描述代碼的上一行。

註解關鍵字後面應該跟一個冒號加一個空格,加一個描述性的註釋。

# FIXME: The client's current state should *not* affect payload processing.
  resetClientState()
  processPayload()

若是註解不止一行,則下一行縮進兩個空格。

# TODO: Ensure that the value returned by this call falls within a certain
  #   range, or throw an exception.
  analyze()

註解有如下幾類:

  • TODO: 描述缺失的功能,以便往後加入
  • FIXME: 描述須要修復的代碼
  • OPTIMIZE: 描述性能低下,或難以優化的代碼
  • HACK: 描述一段值得質疑(或很巧妙)的代碼
  • REVIEW: 描述須要確認其編碼意圖是否正確的代碼

若是你必須自定義一個新的註解類型,則應該把這個註解類型記錄在項目的 README 裏面。

其餘(Miscellaneous)

and 更優於 &&.

or 更優於 ||.

is 更優於 ==.

not 更優於 !.

or= 應在可能的狀況下使用:

temp or= {} # 好
temp = temp || {} # 差

最好用 (::) 訪問對象的原型:

Array::slice # 好
Array.prototype.slice # 差

最好用 @property 而不是 this.property.

return @property # 好
return this.property # 差

可是,避免使用 單獨的 @:

return this # 好
return @ # 差

沒有返回值的時候避免使用 return ,其餘狀況則須要顯示 return 。

當函數須要接收可變數量的參數時,使用 splats (...)。

console.log args... # 好

(a, b, c, rest...) -> # 好

(譯文完)


相關文章
相關標籤/搜索