这份文档包含了一系列CoffeeScript编程语言的最佳实战。
希望能有更多的人一起做贡献,不断丰富文档。
请知晓,这是一个仍然在编写的项目:一些内容可能不符合社区习惯,这些内容会根据实际情况修改或删除。
这份文档的灵感来自与许多风格指南,例如:
- PEP-8: Style Guide for Python Code
- Bozhidar Batsov's Ruby Style Guide
- Google's JavaScript Style Guide
- Common CoffeeScript Idioms
- Thomas Reynolds' CoffeeScript-specific Style Guide
- Jeremy Ashkenas' code review of Spine
- The CoffeeScript FAQ
建议只使用空格键,每 2个空格 作为一个缩进级别,不要混用制表符和空格键。
### 最大行长每行最多包含79个字符
### 空行顶层函数和类声明语句后应空一行。
在类中的函数声明语句后也应当空一行。
在方法或函数内头尾各空一行可以提高代码的可读性。(例如,为了勾勒出代码逻辑部分)
### 尾随空白任何一行都不应该包含有尾随空白。
### 可选的逗号在对象属性或者元素定义,以及需要多行定义的数组中,尽量避免使用逗号。
# 正确
foo = [
'some'
'string'
'values'
]
bar:
label: 'test'
value: 87
# 错误
foo = [
'some',
'string',
'values'
]
bar:
label: 'test',
value: 87
建议使用UTF-8进行源文件编码
## 模块引入当采用模块化系统(例如CommonJs 模块 AMD 等)时,require
语句应当独立成行。
require 'lib/setup'
Backbone = require 'backbone'
模块引入语句应当更具如下顺序进行分组:
- 标准库 (如果引入了标准库)
- 第三方库
- 本地库 (如果引入了本地库)
在下述情况中,避免使用额外的空格
-
在括号中
($ 'body') # 正确 ( $ 'body' ) # 错误
-
逗号前
console.log x, y # 正确 console.log x , y # 错误
额外建议:
-
在下列操作符两边加上 一个空格
-
赋值:
=
-
_定义默认参数的时候也是这样
test: (param = null) -> # 正确 test: (param=null) -> # 错误
-
-
运算操作:
+=
,-=
, etc. -
比较操作:
==
,<
,>
,<=
,>=
,unless
, etc. -
四则运算:
+
,-
,*
,/
, etc. -
(不要用多余一个的空格去包围操作符)
# 正确 x = 1 y = 1 fooBar = 3 # 错误 x = 1 y = 1 fooBar = 3
-
如果修改的代码有相关注释,也应当对注释进行更新,总之,注释应当和代码功能保持一致。
注释的第一个单词应当大写,除非第一个单词必须使用小写字母。
如果注释内容很少,结尾的内容可以省略
### 块级注释块级注释应当写在所要解释的代码块之前。
每行块级注释都应当用#
和一个空格作为开头,并且应当和所要注释的代码保持同样的缩进。
块级注释由仅包含#
的那行行进行分段。
# This is a block comment. Note that if this were a real block
# comment, we would actually be describing the proceeding code.
#
# This is the second paragraph of the same block comment. Note
# that this paragraph was separated from the previous paragraph
# by a line containing a single comment character.
init()
start()
stop()
行内注释应当紧跟所要注释的代码语句之后,如果行内注释内容特别短,可以直接和语句写在一行内(通常在注释前多加一个空格)。
所有的行内注释都应当由一个#
号和一个空格作为开头。
应当尽量限制行内注释的数量,因为他们看起来很像一行代码。
不要去描述那些显而易见的代码运行结果。
# No
x = x + 1 # Increment x
而应当着重描述代码的运行逻辑。
# Yes
x = x + 1 # Compensate for border
使用 camelCase
(驼峰式)的格式去命名所有的变量、方法和对象属性。
使用 CamelCase
去命名所有的类 (这种风格参照了PascalCase
, CamelCaps
, 以及 CapWords
, 在other alternatives中有描述.)
(CoffeeScript的官方命名方式是camelcase,这是为了尽可能的和javascript协作,详情可以参照这里。)
对于常量,命名需要使用大写字母和下划线。
CONSTANT_LIKE_THIS
对于私有的函数和变量在开头应当用下划线标注。
_privateMethod: ->
(这些规则同样适用于类的定义)
当声明的函数中有参数列表,每个参数之间应当也有一个空格进行间隔。
foo = (arg1, arg2) -> # Yes
foo = (arg1, arg2)-> # No
当声明的函数不需要参数,不要插入额外的括号。
bar = -> # Yes
bar = () -> # No
如果需要进行多次链式调用,不要将他们写在一起,每次调用都应当独立成行,并用两个空格进行缩进,用.
开头。
[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 # Braces can also be omitted or included for readability
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() # Initial call only
(($ '#selektor').addClass 'klass').hide() # All calls
这里不推荐使用函数分组,但是,如果某个项目使用函数分组,也请和项目保持一致,使用函数分组的风格
## 字符串在字符串中插入变量而不要手动拼接字符串:
"this is an #{adjective} string" # 正确
"this is an " + adjective + " string" # 错误
除非需求是插入双引号,尽可能的使用单引号 (''
) 而不是双引号 (""
) 字符串,.
使用 unless
而不是 if
处理期望条件不成立的情况.
但是不要使用 unless...else
, 而使用 if...else
:
# 正确
if true
...
else
...
# 错误
unless false
...
else
...
多行的 if/else 应当独立成行并使用缩进:
# 正确
if true
...
else
...
# 错误
if true then ...
else ...
尽可能的使用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
不要修改原生对象
比如不要在Array.prototype
上实现Array#forEach
方法
不要总是忽略异常.
## 注释注释应该用于解释代码执行的特定功能
将注释写在所要描述的代码片段之前
注释关键字和注释正文之间应当由一个冒号和一个空格分隔
# 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文件中。
## 其他and
优于&&
.
or
优于||
.
is
优于==
.
not
优于!
.
尽可能使用or=
:
temp or= {} # 正确
temp = temp || {} # 错误
使用(::
)访问对象的prototype:
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...) -> # 正确