-
80% of the lifetime cost of software goes to maintenance.
-
Hardly any software is maintained for its whole life by the original author.
-
Code conventions improve readability, allowing engineers to understand new code more quickly and thoroughly.
-
Write new code in CoffeeScript.
-
Use soft-tabs with a 2-space indent (this means pressing the tab key once should produce 2 space characters).
-
Try to keep line length 80-90 characters at most.
-
Make sure you do not accidentally include trailing whitespace.
-
Use CamelCaps for class names and constructors.
-
Use camelCase for functions/methods.
-
Use snake_case for variable names.
-
Use a leading underscore (e.g.
_foo
) only for variables and methods that are intended to be "private". -
Use CAPS for constants.
-
Prefix jQuery object variables with a
$
:sidebar = $('.sidebar') # bad $sidebar = $('.sidebar') # good
- Prefer literals (
arr = []
) over native constructors (arr = new Array()
).Array
,Object
, etc constructors are ambiguous in how they deal with their paramameters and they can be overriden. Also, literals are shorter and lint tools like them.
-
Prefer string interpolation over concatenation:
name = 'Maria' console.log 'Ase mas re ' + name + '!' # avoid console.log "Ase mas re #{name}!" # good
-
Use single quotes for strings when not interpolating:
name = "Bob Parr" # bad name = 'Bob Parr' # good
-
Use block strings when it improves readability:
my_msg = 'Password too short!' msg_div = """ <div class="warning_message"> <p> <span>Warning:</span> #{my_msg} </p> </div> """
-
To break a long if statement in multiple lines remember to end each line with an operator
# bad, actually an error if foo is bar and taco is mecca
# good if foo is bar and taco is mecca
-
Prefer dot notation when accessing properties:
luke = jedi: true age: 28 isJedi = luke['jedi'] # bad isJedi = luke.jedi # good
-
Use subscript notation
[]
when accessing properties dynamically (with a variable) or when that property name is a language keyword:options = 'default': bacon: 'nomnom' my_key = 'default' default_food = options['default'] default_food = options[my_key] # same
-
When defining an object in many lines, do not use commas:
# good (no commas) luke = jedi: true age: 28 human: true # bad (commas) luke = jedi: true, age: 28, human: true # bad bad bad (mixed) luke = jedi: true, # comma age: 28 # no comma human: true
-
Do not use parentheses when defining functions that take no arguments:
# bad foo = () -> console.log('aha!') # good foo = -> console.log('aha!')
-
Parentheses in function calls may be omitted with respect to readability and clarity. Some examples:
foo() # you cannot omit () if there are no arguments! foo 4 foo(4).bar(5) foo.getSize(5, 6) / foo.getSize(6, 5)
-
Avoid "function grouping":
(foo 4).bar 8 # bad foo(4).bar 8 # good
-
Avoid creating functions inside loops since it's bad for performance:
# bad for i in [1..100] doSomething = -> console.log(i) doSomething() # good doSomething = (i) -> console.log(i) for i in [1..100] doSomething(i)
-
Avoid explicit
return
statements unless it's for an "early return". For example:browser = getBrowser() return 'oh no!' if 'ie6' # ...cool stuff ie6 doesn't support...
-
Class methods should return
this
to enable method chaining. For example:Jedi = -> @jumping = false @yelling = false Jedi::jump = -> @jumping = true return this Jedi::yell = -> @yelling = true return this first = new Jedi first.jump().yell()
-
Try to incorporate OOP methodologies when applicable.
class Magician # public class property @DISTRACTION_DURATION: '2mins' # private instance function distractAudience = (duration) -> "I will distract them for #{duration}" # public instance function doTrick: -> # call the instance function with a public class property distractAudience(@constructor.DISTRACTION_DURATION)
-
Initialize variables at the top of their scope, preferably in a grouped block.
-
Prefix with _ unused function parameters and local variables. It's also acceptable to use just _ (although it's a bit less descriptive).
-
Place an empty newline at the end of the file (most modern editors will do this automatically for you).
-
Place one space before arrows:
test =-> print 'test' # bad test = -> print 'test' # good test2 = (arg)-> print arg # bad test2 = (arg) -> print arg # good
-
Insert an extra space before and after operators:
foo='bar' # bad foo = 'bar' # good c = a+b # bad c = a + b # good
-
Insert an extra space after
,
and:
:foo: [1,2,3] # bad foo: [1, 2, 3] # good foo:'bar' # bad foo: 'bar' # good
-
Avoid spaces around arguments and before a comma
,
:foo( options, 'bar' ) # bad foo(options , 'bar') # bad foo(options, 'bar') # good
-
Avoid spaces around conditional constructs, loops, etc..
if(true) #bad if (true) #better if true #good
-
Assignments should be vertically aligned unless they differ a lot in length or they are less than 3:
# bad a = 'once' little = 'little' bird = 'bird' told = 'told' me = 'me' # good a = 'once' little = 'little' bird = 'bird' told = 'told' me = 'me' # bad a = 'once' little = 'little' bird_told_me_some_things = 'foo' # bad (this is too much) a = 'once' little = 'little'
-
Break long method chains into many lines, keeping the dot at the beginning of each line:
# bad $('#items').find('.selected').highlight().end().find('.open').updateCount() # good $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount() # even better $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount()
-
Do not write comments to state the obvious.
-
When modifying code, don't forget to update the corresponding comment. Ideally, improve the code to obviate the need for the comment and delete the comment entirely.
-
Do not write comments in CAPS (
TODO
,FIXME
, etc are notable exceptions). -
Short comments should be placed exactly above the code they document, unless they are short enough to be placed on the same line (inline comment).
-
You are free to write block comments using either the triple
#
syntax (###
) or by prefixing each line with a#
:# This # is # a # block # comment ### And another one. This style helps the maintainance of documentation. Each time I want to add or remove a line, I don't have to mess with any #. I also want this comment to be passed to the generated JavaScript. ###
-
Use
parseInt
with a radix for type casting to integers. If, for whatever reason, you are doing something wild andparseInt
is your bottleneck and need to use bitshift for performance reasons, leave a comment explaining why and what you're doing.inputValue = '4' # bad val = parseInt inputValue # good val = parseInt(inputValue, 10) # good val = ~~inputValue # comment here
-
Converting to a boolean:
age = 0 # bad hasAge = Boolean age # good hasAge = !!age # good (ternary operator equivalent) hasAge = if age then true else false
-
You should be able to tell a presentational class attribute from a functional one:
$my_carousel = $('.carousel') # bad $my_carousel = $('.js-carousel') # good
-
Assumption is the mother of all fckups. Do not code with assumptions about DOM hierarchy/state.
-
Cache DOM lookups:
# bad setSidebar = -> $('.sidebar').hide() # ...stuff... $('.sidebar').css({'background-color': 'pink'}) # good setSidebar = -> $sidebar = $('.sidebar') $sidebar.hide() # ...stuff... $sidebar.css({'background-color': 'pink'})
-
Think about performance when writing DOM queries. Try to make the selector engine use the browser's querySelectorAll method. Also a good read: w3c selectors-api
# slow # uses $.sibling internally to find nodes following other nodes in the same tree $('.sidebar').children('ul').hide() # faster $('.sidebar').find('ul').hide()
-
Have a look at the full list of CoffeeScript aliases. Some are notorious for causing confusion to CoffeeScript n00bs.
-
Avoid
==
and!=
as they compile to===
and!==
that may be confusing/unwanted. -
Use
@
instead ofthis
. -
Use fat arrows
=>
in a function definition when you need to bind to the function the current context (this
). -
Learn about the Existential Operator
?
and use it. -
Do not confuse the existential operator
?
with the JavaScript ternary operator. The ternary operator in CoffeeScript is a single-lineif
:my_state = if 6 then 'go!' else 'work!'
-
Use the more explicit
if foo?
(will execute unlessfoo
isundefined
ornull
) instead ofif foo
.
-
Do not use
unless
since it's really confusing. Useif !
orif not
instead. -
When a
.coffee
file is to be preprocessed by let's sayerb
avoid nesting quotes of the same type, as it breaks linting and may make it unparseable by other preprocessors.Example
message = '<%= _('ΣΜΣ') %>' # bad message = '<%= _("ΣΜΣ") %>' # good
Set soft-tabs and rulers according to conventions.
In your ~/.vimrc
add:
set expandtab
set tabstop=2
set shiftwidth=2
set smarttab
set colorcolumn=80,90
Set soft-tabs and rulers according to conventions.
Go to "Preferences -> Settings - User" and add:
"translate_tabs_to_spaces": true,
"tab_size": 2,
"rulers": [ 80, 90 ]
-
Mobile
Connect an Android device via USB to the desktop. Enable debug code execution on the device with the Chrome Developer Tools.
$> adb forward tcp:9222 localabstract:chrome_devtools_remote $> chrome.exe --remote-debugging-port=9222
Another tool for this job is aardwolf
Also see chrome dev tools - device emulation for network capability emulation use network-link-conditioner (mac) and trickle (linux)
-
Firebug (download)
-
Regular Expressions. They are a programmer's best and worst friend. Debug with debuggex.
-
LiveReload. Apply changes in JS, styles without refreshing: extension gem
- Devdocs
- MDN
- WebPlatform
- W3C JavaScript APIs
- Annotated ECMAScript 5.1
- JavaScript Garden
- Javascriptoo
- jsfuck(Fun)
- wtfjs (Fun fun)
- Github
- Airbnb
- Idiomatic
- polarmobile CoffeeScript style guide
- Naming
this
in nested functions - Conditional callbacks
- JavaScript: The Good Parts
- JavaScript Patterns
- Pro JavaScript Design Patterns
- High Performance Web Sites: Essential Knowledge for Front-End Engineers
- Maintainable JavaScript
- JavaScript Web Applications
- Pro JavaScript Techniques
- Smashing Node.js: JavaScript Everywhere
- The Little Book on CoffeeScript
- CoffeeScript Cookbook
- CoffeeScript: Accelerated JavaScript Development
- echojs
- DailyJS
- html5rocks
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- Dustin Diaz
- nettuts
- webplatform
- creativejs
Remember: When in doubt, benchmark.