A JavaScript Quality Guide
github.com
github.com
Let the computer yell at people so you don't have to.
Nobody wants to be the pedantic jerk who has to leave comments on a PR about whitespace or single vs double quotes.
When you use an automated style checker, you presumably catch those errors before a PR gets submitted and nobody ever has to be the bad guy/girl.
Absolutely. We've found automated style checking also improves quality and efficiency. Even the "pedantic jerk" can miss small style issues that are easily caught by tooling.
For anyone wondering what tools. The most common for JS are JSHint and JSCS. Then use Grunt or Gulp combined with a watch to check a file each time a change is saved. Lastly, use a precommit hook (or similar) to check again before code is committed into the repo.
function foo() {
}
and var foo = function() {
};
Was that with the first form foo() will always be declared and available for use inside a scope, while the second form depends at which point it is declared.But I had read somewhere (can't remember where... jshint?) a long while ago that using the latter form inside scopes was better, so I've adopted that.
I don't think I will go with the guide for this one, since not having the function defined automatically is often useful, to avoid overhead of instantiating the function for when it's not going to be used due to code flow.
With overhead, the approach I try to stick to is unless the code become more difficult to grasp, avoid overheads, however small they may be, whenever they can be avoided. Everything adds up in the end.
I much prefer dealing with the "weird" "confusion" hoisting behavior than with not having a named function in my stack trace.
var foo = function foo() {
};
EDIT: The reason it's better to avoid hoisting is because global variables are almost always wrong.Here's why you shouldn't rely on function hoisting: it gets weird. Weird enough that MDN has a section on it's "oddities" [0]. And since it doesn't add any expressive power, there's no compelling reason not to just treat all your code as data.
[0]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I tend to limit them to "private" module functions. e.g.,
"use strict";
/*global module:true*/
function add(a, b) {
return a+b;
}
module.exports = {
sum : function(list) {
return list.reduce(add, 0);
}
};
I don't declare named functions in a scope smaller than the module itself, so I don't really run into the 'weirdness' of hoisting.Then again, I've moved to commonjs style modules for everything - server side with node, client side with browserify (webpack does weird things with require()).
var foo;
...
foo = function() {
}
Also another difference in the latter is that its an anonymous function, which is commonly seen in assignment expressions — but you could also name it for more informative logging. var foo = function realName(){};> var foo = function realName(){};
Nice trick, thanks! The "anonymous" function is especially annoying when profiling code, so that should address that annoyance. I often struggle with picking names, but another post here shows that "foo" can just be reused as the function name.
I'd be very careful about giving them the same name if you're working with IE at all. IE8 and below's JScript does some really strange stuff with function expressions, leaking and hoisting them all over the place. [1]
Instead, I'd just append a character or something to differentiate the two. I've been using the format advocated for in Javascript Patterns[2][3]:
var foo = function fooF(){};
[1] http://kangax.github.io/nfe/#jscript-bugs[2] http://shichuan.github.io/javascript-patterns/
[3] https://github.com/shichuan/javascript-patterns/blob/master/...
So, if you have code or logging that assumes all functions have names, then the code may break or degrade when built and deployed in production.
I've prefer the latter as it better illustrates the way JavaScript actually works, with all methods being lambdas. The prior is just too magic.
'use strict'; should be in the top of the scope you control. A global 'use strict'; would place the global scope into strict mode, so all your imported modules would be under strict mode too, and then third party code would break and you don't know why. IIRC jshint will pick this up.
To be honest, the whole guide seems like a shorter, less comprehensive version of the JS community's own Idiomatic JS https://github.com/rwaldron/idiomatic.js/
Moreover, a few of the suggestions introduce serious performance issues, notably around iteration and the treatment of the `arguments` object. If you haven't yet, please do check out Petka Antonov's Optimization Killers [0].
[0]: https://github.com/petkaantonov/bluebird/wiki/Optimization-k...
A common example: lodash searches function toString() with regexps as an optimisation technique, underscore doesn't. Both are correct, maintaining lodash requires knowledge of how and why the hack works, but OTOH lodash is faster. Maintaining underscore is cognitively simpler but the resulting code is slower.
Here is the specific remark I was referring to: Or even better, just use .forEach which doesn't have the same caveats as declaring functions in for loops.
Blindly applying forEach is simply not the right answer here.
Should we use a .forEach() for a 1 million item array? No. Performance would be a problem. For the typical use case of items like the demo [1, 2, 3]? Yes, this would be be simpler.
[1] = https://github.com/rwaldron/idiomatic.js/
[2] = https://google-styleguide.googlecode.com/svn/trunk/javascrip...
Although it might introduce inadvertent bugs. I prefer not to follow that advice to avoid running into the 'lastIndex' problem described here [1]. There are other ways to avoid it like not using the 'g' flag or resetting lastIndex. However not storing regex in a variable is also useful to avoid that headache. You might argue about performance but for a good majority of the cases, it doesn't matter practically.
[1] http://stackoverflow.com/questions/1520800/why-regexp-with-g...
[2] http://stackoverflow.com/questions/13500519/difference-betwe...
Semicolons ;
It seems to be fashionable recently to omit semicolons from Javascript. For example GitHub (internal) and zepto.js have jumped on the no-semicolon bandwagon, requiring their omission in any code.http://programmers.stackexchange.com/questions/142086/why-th...
OP's guide mentions "Avoid headaches, avoid ASI. Always add semicolons where needed", that's a good advice IMHO.
Edit: I would add: http://programmers.stackexchange.com/a/142114
Perhaps overly pedantic, but this seems a little...vague.
return
{
a: 0
};
since you can't disable ASI. Even in the above case, however, "standard" JS style would prevent the issue.If what you are saying is with "standard JS style" you will never add a newline after return, then I can also assume with "standard JS style" you will not:
- start a line with ++ or --
- start a line with a regex literal
- split a for statement into separate lines
So, the only issue you need to be aware of when writing semicolon-less javascript is when you start a new line with ( or [. Easy enough to remember, no?
I've personally been writing semicolon-less JS for almost two years now, and this one simple rule has been more than enough.
Aren't many of the other suggestions precisely "style checking" concerns? Semicolons, spacing, string quotes, conditional brackets, etc. ?
Not to say that there isn't a difference -- just that I don't see what it is.
"Style checking" means "Automated style checkers such as jscs"jshint is a static code analysis tool to identify and flag errors/potential errors in JS code. jscs is purely a style checker.
Really how you place your {} will never make or break your project. Focus on what really matters.
var message = util.format('oh hai %s!', name);
I thought it was a javascript quality guide ? there is no util.format in ES5 spec.I don't think you can ask more than this, everything is clearly laid out...
Important is to configure once your favorite Editor and use it consequent.
Not only does it remove the 2 vs 4 spaces debate (just set your browser preferences to display it as whatever!), it's more 'semantically correct' - it's literally saying "one level of indentation please".
Anyway, not that I particularly care - I just always found it amusing that this is where developers have chosen against things being semantically correct and user-configurable.
var foo = SomeTerriblyLongHorrificClass->withUnreasonablyLargeChildren()
->dueToTheOddNumberOfCharachters()
->sometimesItsNiceToUseSpaces()
->here()