CoffeeScript Style Guide
This guide presents a collection of best-practices and coding conventions for the CoffeeScript programming language.
This guide is intended to be community-driven, and contributions are highly encouraged.
Please note that this is a work-in-progress: there is much more that can be specified, and some of the guidelines that have been specified may not be deemed to be idiomatic by the community (in which case, these offending guidelines will be modified or removed, as appropriate).
The details in this guide have been very heavily inspired by several existing style guides and other resources. In particular:
- PEP-8: Style Guide for Python Code
- Bozhidar Batsov's Ruby Style Guide
- Common CoffeeScript Idioms
- Thomas Reynolds' CoffeeScript-specific Style Guide
- Jeremy Ashkenas' code review of Spine
- The CoffeeScript FAQ
Run coffeelint with this guide
This repository can be installed and used to lint coffescript files using the configuration found in the coffeelint config file. List this repository as a dependency in the
package.json and add the following to your Makefile:
lint: node_modules/.bin/lint [files]
lint can also be added as the final dependency of
test to increase its visibility.
Files must either be specified by their absolute path, or their path relative to the Makefile's directory. If no files are specified and you are in a git repository all
.coffee files in that repository will be linted. If you are not in a git repository all
.coffee files in the current directory and all subdirectories (except
node_modules) will be linted.
Table of Contents
- The CoffeeScript Style Guide
- Code Layout
- Module Imports
- Whitespace in Expressions and Statements
- Naming Conventions
- Looping and Comprehensions
- Extending Native Objects
Use spaces only, with 2 spaces per indentation level. Never mix tabs and spaces.### Maximum Line Length
Limit all lines to a maximum of 100 characters.### Blank Lines
Separate top-level function and class definitions with a single blank line.
Separate method definitions inside of a class with a single blank line.
Use a single blank line within the bodies of methods or functions in cases where this improves readability (e.g., for the purpose of delineating logical sections).### Trailing Whitespace
Do not include trailing whitespace on any lines.### Encoding
UTF-8 is the preferred source file encoding.## Module Imports
If using a module system (CommonJS Modules, AMD, etc.),
require statements should be placed on separate lines.
require 'lib/setup'Backbone = require 'backbone'
These statements should be grouped in the following order:
- Standard library imports (if a standard library exists)
- Third party library imports
- Local imports (imports specific to this application or library)
Avoid extraneous whitespace in the following situations:
Immediately inside parentheses, brackets or braces$ 'body' # Yes$ 'body' # No
Immediately before a commaconsolelog xy # Yesconsolelog x y # No
Always surround these binary operators with a single space on either side
Note that this also applies when indicating default parameter value(s) in a function declaration: # Yes: # No
(Do not use more than one space around these operators)# Yesx = 1y = 1fooBar = 3# Nox = 1y = 1fooBar = 3
If modifying code that is described by an existing comment, update the comment such that it accurately reflects the new code. (Ideally, improve the code to obviate the need for the comment, and delete the comment entirely.)
The first word of the comment should be capitalized, unless the first word is an identifier that begins with a lower-case letter.
If a comment is short, the period at the end can be omitted.### Block Comments
Block comments apply to the block of code that follows them.
Each line of a block comment starts with a
# and a single space, and should be indented at the same level of the code that it describes.
Paragraphs inside of block comments are separated by a line containing a single
# 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.initstartstop
Inline comments are placed on the line immediately above the statement that they are describing. If the inline comment is sufficiently short, it can be placed on the same line as the statement (separated by a single space from the end of the statement).
All inline comments should start with a
# and a single space.
The use of inline comments should be limited, because their existence is typically a sign of a code smell.
Do not use inline comments when they state the obvious:
# Nox = x + 1 # Increment x
However, inline comments can be useful in certain scenarios:
# Yesx = x + 1 # Compensate for border
snake_case (with a leading lowercase character) to name all variables, methods, and object properties.
CamelCase (with a leading uppercase character) to name all classes. (This style is also commonly referred to as
CapWords, among other alternatives.)
For constants, use all uppercase with underscores:
Methods and variables that are intended to be "private" should begin with a leading underscore:
(These guidelines also apply to the methods of a class.)
When declaring a function that takes arguments, always use a single space after the closing parenthesis of the arguments list:
= # Yes= # No
Do not use parentheses when declaring functions that take no arguments:
= -> # Yes= # No
Only use the fat arrow syntax when
this is needed within the function body:
= => 1 # No= => @bang # Yes
In cases where method calls are being chained and the code does not fit on a single line, each call should be placed on a separate line and indented by one level (i.e., two spaces), with a leading
1..3map x * xconcat10..12filter x < 11reduce x + y
When calling functions, choose to omit or include parentheses in such a way that optimizes for readability. Keeping in mind that "readability" can be subjective, the following examples demonstrate cases where parentheses have been omitted or included in a manner that the community deems to be optimal:
baz 12brushellipse x: 10y: 20 # Braces can also be omitted or included for readabilityfoo4bar8objvalue1020 / objvalue2010print inspect valueabc
You will sometimes see parentheses used to group functions (instead of being used to group function parameters). Examples of using this style (hereafter referred to as the "function grouping style"):
$ '#selektor'addClass 'klass'foo 4bar 8
This is in contrast to:
$'#selektor'addClass 'klass'foo4bar 8
In cases where method calls are being chained, some adopters of this style prefer to use function grouping for the initial call only:
$ '#selektor'addClass'klass'hide # Initial call only$ '#selektor'addClass 'klass'hide # All calls
The function grouping style is not recommended. However, if the function grouping style is adopted for a particular project, be consistent with its usage.
Don't assign default arguments in front of positional arguments:
= # No= # Yes
Use string interpolation instead of string concatenation:
"this is an string" # Yes"this is an " + adjective + " string" # No
Prefer single quoted strings (
'') instead of double quoted (
"") strings, unless features like string interpolation are being used for the given string.
if for negative conditions.
Instead of using
# Yesif true...else...# Nounless false...else...
Multi-line if/else clauses should use indentation:
# Yesif true...else...# Noif true then ...else ...
Take advantage of comprehensions whenever possible:
# Yesresult = itemname for item in array# Noresults =for item in arrayresultspush itemname
result = item for item in array when itemname is "test"
To iterate over the keys and values of objects:
object = one: 1two: 2alert" = " for keyvalue of object
Do not modify native objects.
For example, do not modify
Array.prototype to introduce
Do not suppress exceptions.## Annotations
Use annotations when necessary to describe a specific action that must be taken against the indicated block of code.
Write the annotation on the line immediately above the code that the annotation is describing.
The annotation keyword should be followed by a colon and a space, and a descriptive note.
# FIXME: The client's current state should *not* affect payload processing.resetClientStateprocessPayload
If multiple lines are required by the description, indent subsequent lines with two spaces:
# TODO: Ensure that the value returned by this call falls within a certain# range, or throw an exception.analyze
TODO: describe missing functionality that should be added at a later date
FIXME: describe broken code that must be fixed
OPTIMIZE: describe code that is inefficient and may become a bottleneck
HACK: describe the use of a questionable (or ingenious) coding practice
REVIEW: describe code that should be reviewed to confirm implementation
If a custom annotation is required, the annotation should be documented in the project's README.## Miscellaneous
and is preferred over
or is preferred over
is is preferred over
not is preferred over
or= should be used when possible:
temp or= # Yestemp = temp || # No
Prefer shorthand notation (
::) for accessing an object's prototype:
Array::slice # YesArrayprototypeslice # No
return @property # Yesreturn thisproperty # Noreturn @ # Yesreturn this # No
return where not required, unless the explicit return increases clarity.
Use splats (
...) when working with functions that accept variable numbers of arguments:
consolelog args... # Yes# Yes