There are style-guides already available for JavaScript and indeed, at least 3 tools for linting and verifying styles. Why do we need another?
This styleguide is different in that it is focused on teaching & learning JS, starting with front-end JavaScript and CSS and eventually teaching jQuery, Node, Express and friends. When we teach we generally increase complexity over time. This guide aims to set guidelines to ensure that syntax across lessons is the same, while slowly introducing additional syntactical complexity.
tldr; This style-guide is intended to make learning easier for students new to JavaScript by increasing syntactical complexity slowly, over time.
/* avoid tabs */
.ridiculously-huge {
font-size: 100px;
}
/* recommended */
.ridiculously-huge {
font-size: 100px;
}
Choose ===
and !==
over ==
and !=
. [link]
// avoid
if (test)
return false;
// recommended - single line
if (test) return false;
// recommended - multi-line
if (test) {
return false;
}
// avoid
var stuff = new Array();
// recommended
var items = [];
// avoid
someStuff[someStuff.length] = 'new todo';
// recommended
someStuff.push('new todo');
- It's safer if the return values are ever extended.
- Avoids mistakes in handling return value order.
// avoid
function processInput(input) {
// ...
return [strangeness, spin, charm];
}
// recommended
function processInput(input) {
// ...
return { strangeness: strangeness,
spin: spin,
charm: charm };
}
Strings that cause the line to exceed ~100 characters should be concatenated across multiple lines.
// avoid
var html = '<ol><li>Of shoes</li><li>and ships</li><li>and sealing-wax</li><li>Of cabbages</li><li>and kings</li></ol>'; // Lewis Carroll
// less bad
var html = '<ol> \
<li>Of shoes</li> \
<li>and ships</li> \
<li>and sealing-wax</li> \
<li>Of cabbages</li> \
<li>and kings</li> \
</ol>'; // Lewis Carroll
// recommended
var html = (
'<ol>' +
'<li>Of shoes</li>' +
'<li>and ships</li>' +
'<li>and sealing-wax</li>' +
'<li>Of cabbages</li>' +
'<li>and kings</li>' +
'</ol>' // Lewis Carroll
);
// avoid
function yay(){
console.log('yay');
}
// recommended
function yay() {
console.log('yay');
}
// avoid
if(x === y) {
return x;
}
// recommended
if (x === y) {
return x;
}
// avoid
a=b+c-(d/2);
// recommended
a = b + c - (d / 2);
// avoid
function addNumbers( a, b ) { ... }
// recommended
function addNumbers(a,b) { ... }
function calls:
// avoid
var addedNumbers = addNumbers( 1, x );
// recommended
var addedNumbers = addNumbers(1, x);
// OK
var saute = function () { ... };
// also OK
var saute = function() { ... };
// avoid
//my comment with no space
// avoid
/* This is a comment that doesn't
use indentation when continuing a sentence. */
// recommended
// my comment with a space
/* This is a comment that does
use indentation when continuing a sentence. */
// avoid
$('#items').
find('.selected').
highlight().
end().
find('.open').
updateCount();
// recommended
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
Example lifted from airbnb style-guide.
This rule is particularly important in the first 2-3 weeks of the course. However, we should eventually introduce and use anonymous functions.
// avoid
$.get(url).success(function(result) {
console.log(result);
});
// recommended
$.get(url).success(handleIndexResult(result));
// sometimes OK
$.get(url).success(function handleIndexResult(result) {
console.log(result);
});
- Function declarations are fully hoisted.
// bad
var boilPasta = function () {
};
// recommended
function boilPasta() {
}
Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead.
- It overrides the arguments object the function receives.
// avoid
function nope(name, options, arguments) {
// ...stuff...
}
// recommended
function yup(name, options, args) {
// ...stuff...
}
lifted from airbnb
// avoid
function cat() {
this.sound = 'meow';
}
var kitten = new cat;
// recommended
function Cat() {
}
var kitten = new Cat;
Thanks Justin
// Using the core $.ajax() method
$.ajax({
// The URL for the request
url: "post.php",
// The data to send (will be converted to a query string)
data: {
id: 123
},
// Whether this is a POST or GET request
type: "GET",
// The type of data we expect back
dataType : "json",
// Code to run if the request succeeds;
// the response is passed to the function
success: onSuccess,
// Code to run if the request fails; the raw request and
// status codes are passed to the function
error: onError,
// Code to run regardless of success or failure
complete: onComplete
});
function onSuccess( json ) {
$("<h1>").text(json.title).appendTo("body");
$("<div class=\"content\">").html(json.html).appendTo("body");
}
function onError(xhr, status, errorThrown) {
alert("Sorry, there was a problem!");
console.log("Error: " + errorThrown);
console.log("Status: " + status);
console.dir(xhr);
}
function onComplete( xhr, status ) {
alert("The request is complete!");
}
- This makes the syntax identical for the more difficult PUT and DELETE operations.
- Eventually students will discover the short-cut methods on their own; we should allow them to use them at that point.
// avoid
$.get("http://pokemon.com/api/pokemon").success(renderPokemonList(json));
// recommended
$.ajax({
url: "http://pokemon.com/api/pokemon",
type: "GET",
dataType : "json",
success: renderPokemonList,
error: handlePokemonIndexError,
});
function renderPokemonList(json) { ... }
- In-line function definitions are hard to read and hard for students to find syntax errors around.
- See above rule on anonymous functions as well.
// avoid
$.ajax({
url: "http://pizza.com/api/toppings",
type: "GET",
// named in-line function (avoid)
success: function populateToppingsList(data) {
// possibly many lines of code
// possibly many lines of code
},
// anonymous in-line function (avoid)
error: function(xhr, status, errorThrown) {
// possibly many lines of code
// possibly many lines of code
},
});
// recommended
function populateToppingsList(data) {
// many lines of code
}
function handleToppingsError(xhr, status, errorThrown) {
// many lines of code
}
$.ajax({
url: "http://pizza.com/api/toppings",
type: "GET",
success: populateToppingsList,
error: handleToppingsError,
});
├── README.md ├── index.html ├── scripts │ └── app.js ├── styles │ └── styles.css └── images └── spinner.gif
Main example:
. ├── server.js ├── config │ └── routes.js ├── controllers │ └── quotesController.js ├── models │ ├── index.js │ └── quote.js ├── package.json ├── public │ └── styles │ └── styles.css │ └── scripts │ └── app.js └── views ├── partials │ ├── footer.hbs │ ├── head.hbs │ └── header.hbs └── quotes ├── index.hbs └── new.hbs
- This follows GA-global curriculum except we use
server.js
instead ofapp.js
(which we reserve for the client).
. ├── server.js ├── config │ └── routes.js └── models ├── index.js └── quote.js
- promote use of the module pattern