Skip to content

Instantly share code, notes, and snippets.

@isaacs
Created March 30, 2009 23:20
Show Gist options
  • Save isaacs/87947 to your computer and use it in GitHub Desktop.
Save isaacs/87947 to your computer and use it in GitHub Desktop.

Use tabs for indentation.

This is not up for debate. Please configure your editor to use tabs instead of spaces. Tabs let everyone use the level of indentation that they prefer.

PascalClass for classes and singletons, camelCase for variables, functions, and members, css-case for HTML classes/IDs and file/folder names.

Example:

MyClass = function () {...};
var myObj = new MyClass();

MySingleton = (function () {...})();
MySingleton.doSomething();

<div class="some-class" id="the-only-one">

project-name/src/some-component/some-file.js

Space before the ( for everything except function calls.

For example:

var bar = function () {};
if (foo) ...
while (go) ...
bar();

This makes function calls very explicit.

Function declarations

Use var syntax for callable functions. Wrap closures and immediate-returns in parens.

var f = function () { ...doSomething... };
var o = (function () { return something; })();
(function () {
	... do something private
})();

In the o = (function () {..})() case, the parens are not strictly necessary. However, this makes it clear that o is being set to the return value of the function, and not the function itself.

The function.name property is interesting and occasionally useful. It is read-only, and creates a protected entry in the scope chain corresponding to the function's name. If you need to use this property, then name the function explicitly, but still use the var syntax, so that it is clear that the function name is relevant. For example:

var foo = function foo () {};

Since arguments.callee is deprecated, this is occasionally important even in closures and otherwise anonymous functions. For example:

(function X () {
	// do something
	window.setTimeout(X, 1000);
})();

functionThatTakesAFunction(function bar () {
	// do something, refer to "bar"
});

It is not necessary for the names to match:

var PublicName = function privateName () {};

Note that in IE <= 7, "PublicName" and "privateName" are not the same object! This is a very strange bug. So, for client-side code, use arguments.callee || privateName just to be safe.

Semicolons

Almost every line should end in a semicolon. Don't rely on semicolon-insertion.

The only lines that don't need semicolons are the } at the end of non-function blocks. (Such as while, for, if, etc.)

When in doubt, add the semicolon. It never hurts.

Keep lines below 80 characters in length (and carriage-return/indent to maintain this rule)

80 characters is a rough guideline. In general, each line should have a single meaningful statement, and will usually be much shorter than 80 characters. For example:

if (
	condition1 ||
	condition2 && condition3
) doSomething();

If there is a line-break after the ), use braces. Otherwise, don't.

These are ok:

if (condition) doSomething();
if (
	condition1 ||
	condition2 && condition3
) doSomething();
if (condition) {
	doSomething();
	doSomethingElse();
}

These are not ok:

if (condition)
	doSomething();

if (condition) { doSomething(); }

In general, if there is a single small line in the block, put it on the same line as the closing paren, and don't use braces. Never use braces for an inline statement.

The only exceptions to the "inline braces" issue is an empty function or object literal. These are acceptable:

f = function () {};
o = {};

Braces on the same line as the thing that starts them.

This is ok:

if (foo) {

This is not ok:

if (foo)
{

elses are butterflies

Put the else on the same line as the } and {. Like this:

if (foo) {
	doSomething();
} else {
	doSomethingElse();
}

Prefer chaining single-line blocks over nested braces

This is better:

if (
	condition1 || condition2
) for (
	var i in obj
) if (
	obj.hasOwnProperty(i) &&
	obj[i].length
) for (
	var j = 0, l = obj[i].length; j < l; j ++
) doSomething(obj[i][j]);

This is less better:

if (condition1 || condition2) {
	for (var i in obj) {
		if (obj.hasOwnProperty(i) && obj[i].length) {
			for (var j = 0, l = obj[i].length; j < l; j ++) {
				doSomething(obj[i][j]);
			}
		}
	}
}

In general, try to avoid having more levels of indentation than necessary.

Abort early to reduce the size of braced blocks

This is good:

var foo = function (x) {
	if (!x) return false;
	// .. do lots of stuff with x ..
	return x;
}

This is not good:

var foo = function (x) {
	if (x) {
		// .. do lots of stuff with x ..
		return x;
	}
	return false;
}

This is even worse:

var foo = function (x) {
	if (x) {
		// .. do lots of stuff with x ..
		return x;
	} else {
		// .. do lots more stuff to handle the error ..
		return false;
	}
}

In that case, the "foo" function should really be two functions, which leads us to:

Functions should be discrete meaningful actions

Name your functions as a verb that describes what they do. They should do one thing. If that thing needs other things to be done, then they should call other, less abstract helper functions.

This keeps functions small, useful, and easy to read.

Hide data that doesn't need to be exposed

If it's exposed, it's part of the API. APIs should only contain items that are relevant to implementors.

Don't rely on conventions like _memberName to mark things as private. If you want it to be private, then don't expose it at all.

Don't use the "hanging arguments" syntax.

This is very bad:

mySuperAwesomeLongNamedFunction(thefirstargument,
                                thesecondargument,
                                theThirdArgument,
                                moreArguments);

Instead, do it like this:

mySuperAwesomeLongNamedFunction(
	thefirstargument,
	thesecondargument,
	theThirdArgument,
	moreArguments
);

It's bad for 2 reasons. First, it pretty much only works if you're using spaces for indentation, or if everyone has the same tabstops. The whole point of using tabs for indentation is that different people like different tabstops.

Second, when you have lots of long function names that are different lengths, it looks ridiculous.

mySuperAwesomeLongNamedFunction(thefirstargument,
                                thesecondargument,
                                theThirdArgument,
                                moreArguments);
myLessAwesomeFunction(thefirstargument,
                      thesecondargument,
                      theThirdArgument,
                      moreArguments);
myOtherLessAwesomeFunction(thefirstargument,
                           thesecondargument,
                           theThirdArgument,
                           moreArguments);

Don't try to "line up" key/value sets

For the same reason that hanging argument lists are bad, this is also bad:

o = {
	someLongKeyName : "value",
	x               : 1,
	foo             : "bar"
};

Never use 12 spaces when 1 will do.

o = {
	someLongKeyName : "value",
	x : 1,
	foo : "bar"
};

Use README files on new directories that you create

If you create a folder, create a README file that says what goes in that folder. It only has to be a line or two.

You can always remove it later if it's really redundant. But usually, it's not, and those files provide helpful navigation cues to wary travelers exploring unfamiliar parts of the code later. Those guidelines will help them stay true to the vision that you have now, when you're creating the folder. It's like a comment in the directory structure.

Code needs comments less than directories, because code tells you what it's doing, whereas a directory just tells you its name, and nothing else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment