Skip to content

Instantly share code, notes, and snippets.

@davidchambers
Created December 8, 2013 19:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidchambers/7862897 to your computer and use it in GitHub Desktop.
Save davidchambers/7862897 to your computer and use it in GitHub Desktop.

CoffeeScript style guide

Literals

Booleans

CoffeeScript provides three keywords which translate to JavaScript's true keyword (yes, on, true), and three which translate to JavaScript's false keyword (no, off, false).

Use whichever reads best (usually yes or no).

Numbers

Never begin a number literal with a period (.):

right = 0.5
wrong = .5
#       ^ number literals should not begin with "."

Omit the sign for positive numbers:

right = 42
wrong = +42
#       ^ unnecessary sign

Don't include a space between sign and number:

right = -42
wrong = - 42
#        ^ unwanted space after sign

Use binary literal notation for bitmasks:

right = permissions = 0b101
wrong = permissions = 5

Don't simplify an arithmetic expression if its meaning would be obscured:

right = 24 * 60 * 60 * 1000
wrong = 86400000

Strings

Favor single quotes:

right = 'Hello, world!'
wrong = "Hello, world!"
#       ^ unnecessarily double-quoted string

Double quotes should be used to avoid having to escape single quotes ('):

right = "It's a beautiful day, isn't it?"
wrong = 'It\'s a beautiful day, isn\'t it?'
#          ^ avoidable backslash (use double-quoted string)

Consider block strings for strings containing both single and double quotes:

right = '''"Don't do that!", said the boy's mother.'''
wrong = '"Don\'t do that!", said the boy\'s mother.'
#            ^ avoidable backslash (use block string)

Use interpolation rather than concatenation:

right = "Hello, #{user.firstName}!"
wrong = 'Hello, ' + user.firstName + '!'

RegExps

Backslashes harm readability and should be avoided. Use a character class when matching a literal period (.), and consider the extended form when matching several slashes (/):

right = /// ^https?://upthere[.]com$ ///
wrong = /^https?:\/\/upthere\.com$/
#                ^ avoidable backslash (use heregex)

Include comments for complex patterns:

re = ///
  ^
  (\d{4})-(\d\d)-(\d\d)     # year-month-date
  [T\x20]                   # "T" or " "
  (\d\d):(\d\d)             # hours:minutes
  (?::(\d\d)(?:[.](\d+))?)? # seconds with optional decimal component
  (?:([-+]\d\d):?(\d\d)|Z)  # time zone offset
  $
///

Since spaces are ignored in heregexes, \x20 should be used to match a literal space ( ).

Arrays

There should be no spaces after the opening square bracket ([) or before the closing square bracket (]):

right = [1, 2, 3]
wrong = [ 1, 2, 3 ]
#        ^ unwanted space after "["

Separate items in single-line array literals with a comma (,) followed by a space ( ):

right = [1, 2, 3]
wrong = [1,2,3]
#          ^ missing space after ","
wrong = [1 , 2 , 3]
#         ^ unwanted space before ","

Omit commas in multi-line array literals:

right = [
  'foo'
  'bar'
  'baz'
]
wrong = [
  'foo',
#      ^ unwanted comma
  'bar',
#      ^ unwanted comma
  'baz'
]

Objects

There should be no spaces after the opening curly bracket ({) or before the closing curly bracket (}):

right = {foo: 1, bar: 2}

wrong = { foo: 1, bar: 2 }
#        ^ unwanted space after "{"

Separate key and value with a colon (:) followed by a space ( ):

right = foo: 1, bar: 2

wrong = foo:1, bar:2
#           ^ missing space after ":"
wrong = foo : 1, bar : 2
#          ^ unwanted space before ":"

Separate entries in single-line object literals with a comma (,) followed by a space ( ):

right = foo: 1, bar: 2

wrong = foo: 1,bar: 2
#              ^ missing space after ","
wrong = foo: 1 , bar: 2
#             ^ unwanted space before ","

Omit commas in multi-line object literals:

right =
  foo: yes
  bar: yes
  baz: 42

wrong =
  foo: yes,
#         ^ unwanted comma
  bar: yes,
#         ^ unwanted comma
  baz: 42

Operators

For certain operators, a space ( ) should be included between operator and operand(s). This section demonstrates the preferred spacing for each operator.

Unary operators

delete y.z
typeof x
++x
--x
+x
-x
~x
!x
not x

Binary operators

# Multiplicative operators
x * y
x / y
x % y

# Additive operators
x + y
x - y

# Bitwise shift operators
x << y
x >> y
x >>> y

# Relational operators
x < y
x > y
x <= y
x >= y
x instanceof y
x of y
x in y
x == y ; x is y   # favor "is"
x != y ; x isnt y # favor "isnt"

# Binary bitwise operators
x & y
x ^ y
x | y

# Binary logical operators
x && y ; x and y  # favor "and"
x || y ; x or y   # favor "or"

Comparison

Use is and isnt rather than == and !=. Rationale: CoffeeScript's == is different from JavaScript's ==, whereas is doesn't exist in JavaScript so cannot cause confusion.

When comparing a variable against a set of values, use in:

right = location.protocol in ['http:', 'https:']

wrong = location.protocol is 'http:' or location.protocol is 'https:'
#                                       ^^^^^^^^^^^^^^^^^^^^ unwanted repetition

When checking whether a variable falls within a range of values, use chained comparison:

right = 200 <= res.statusCode <= 299

wrong = res.statusCode >= 200 and res.statusCode <= 299
#                                 ^^^^^^^^^^^^^^ unwanted repetition

Idioms

Use postfix if for one-liners:

right = true if cond

if cond then wrong = true
#       ^^^^ then clause with no else clause

Use of for membership checks:

right = true if 'foo' of cache
wrong = true if cache.foo

Use "#{...}" to stringify values:

right = "#{x}"
wrong = x.toString()

Use @ in place of this.:

right = "#{@firstName} #{@lastName}"

wrong = "#{this.firstName} #{this.lastName}"
#          ^^^^^ expected "@" shorthand

Don't use @ in place of this:

right = this
wrong = @
#       ^ naked "@" (use "this" instead)

Use :: in place of .prototype.:

right = Object::hasOwnProperty
wrong = Object.prototype.hasOwnProperty
#             ^^^^^^^^^^^ expected "::" shorthand

Don't use :: in place of .prototype:

right = Object.prototype
wrong = Object::
#             ^^ dangling "::" (use ".prototype" instead)

Use @ to assign static properties to a class:

# right
class Foo
  @bar = 42

# wrong
class Foo
  Foo.bar = 42
# ^^^^ expected "@" shorthand

Use the fat arrow (=>) to preserve context:

# right
setTimeout =>
  @dismiss()
, 1000

# wrong
self = this
setTimeout ->
  self.dismiss()
, 1000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment