Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
121 lines (119 sloc) 6.93 KB
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Greasemonkey - Programming Style Guide</title>
<style type="text/css">
pre {
background: none repeat scroll 0 0 #EEEEEE;
border: 1px dashed #666666;
display: block;
font-size: 1.1em;
line-height: 1.1em;
margin: 1ex;
overflow: auto;
padding: 1ex;
white-space: pre;
}
</style>
</head>
<body>
<h1>Greasemonkey - JavaScript Style Guide</h1>
<p>This document describes the JavaScript style for the Greasemonkey project. Below, use of the word "should" is only for its effect on the prose, and actually means "must".</p>
<p>This guide is based on a Mozilla JavaScript Style Guide document which no longer exists (and was previously the Greasemonkey style guide), which in turn was based on a <a href='http://web.archive.org/web/20080328023013/http://web.archive.org/web/20080328023013/http://neil.rashbrook.org/Js.htm'>document by Niel Rashbrook</a>.</p>
<h2>Whitespace</h2>
<ul>
<li>Indent blocks with two spaces. No tabs. Thus, blocks should be indented as:<pre>if (dlmgrWindow) {
dlmgrWindow.focus();
} else {
dlmgr.open(window, null);
}</pre></li>
<li>Lines should be no longer than 80 characters.</li>
<li>When breaking statements across multiple lines, continuation lines should be indented by four spaces (not to align with something on the previous lines). For any "block" (function arguments, object literal contents, etc) the contents should all be on the following indented line, not following the opening brace. Or, bad:
<pre>compMgr.registerFactoryLocation(CID,
CLASSNAME,
CONTRACTID,
fileSpec,
location,
type);</pre>
Bad:
<pre>compMgr.registerFactoryLocation(CID, CLASSNAME, CONTRACTID, fileSpec,
location, type);</pre>
Good:
<pre>compMgr.registerFactoryLocation(
CID, CLASSNAME, CONTRACTID, fileSpec, location, type);</pre>
</li>
<li>Surround binary operators with single spaces.</li>
<li>Put a single space after keywords (if, for, etc).</li>
<li>Two blank lines between "top level" function/method definitions (those in the global scope, or in prototypes; not for locally scoped helper functions). Also consider breaking up distinct sections of code inside functions with blank lines.</li>
<li>Files should contain exactly one newline at the end.</li>
<li>Lines should have no trailing whitespace.</li>
</ul>
<h2>Symbols</h2>
<ul>
<li>Spaces around braces used for in-line functions or objects, except before commas or semicolons, e.g. <pre>function valueObject(aValue) { return { value: aValue }; }</pre></li>
<li>Otherwise spaces are not necessary inside brackets.</li>
<li>Prefer double quotes, except when quoting double quotes.</li>
<li>
Braces on if/else statements are not optional, unless the entire compound statement fits completely on one line.</li>
<li>
When continuing a single statement across a line, operators should be at the beginning of the continued line, including the dot (scope resolution). Examples:
<pre>if (stack.filename != null
&& stack.filename != gmSvcFilename
&& stack.filename.substr(0, 6) != "chrome"
) {
// ...
}
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader);</pre>
</li>
</ul>
<h2>Code Style</h2>
<ul>
<li>Always put else on its own line, as shown in the "Whitespace" section.</li>
<li>Name inline functions, this makes it easier to debug them. Just assigning a function to a property doesn't name the function, you should to do something like: <pre>var offlineObserver = {
observe: function OO_observe(aSubject, aTopic, aState) {
if (aTopic == "network:offline-status-changed")
setOfflineUI(aState == "offline");
}
};</pre>This helps with a number of editing and debugging tools.</li>
</ul>
<h2>Function and variable naming</h2>
<ul>
<li>Unless otherwise specified, use camelCasedNames.</li>
<li>Constants should be in <code>UPPER_CASE</code>.</li>
<li>Use InterCaps and capitalize the first letter of constructors.</li>
<li>Do not pollute the global namespace. Global (chrome window scoped) definitions should be avoided, but at least use a <code>GM_</code> name prefix.</li>
<li>Global state variables should be prefixed with the letter <code>g</code>, e.g. <code>gFormatToolbar</code>.</li>
<li>Arguments (parameter names) should be prefixed with the letter <code>a</code>.</li>
<li>Private members should start with <code>_</code>, e.g. <code>_internalFunction</code>. They should not be accessed except by the class they are a member of.</li>
<li>Event handler functions should be prefixed with the word on, in particular try to use the names onLoad, onDialogAccept, onDialogCancel, etc., where this is unambiguous.</li>
<li>Function names, local variables, and object members have no prefix.</li>
<li>Try to declare local variables as near to their use as possible; initialize every variable.</li>
<li>Only declare a variable once in each scope.</li>
</ul>
<h2>JavaScript Features</h2>
<ul>
<li>Make sure that your code doesn't generate any strict JavaScript
warnings, such as:
<ul>
<li>Duplicate variable declaration</li>
<li>Mixing <code>return;</code> with <code>return value;</code></li>
<li>Trailing comma in JavaScript object declarations.</li>
</ul>
</li>
<li>Use <code>[value1, value2]</code> to create a JavaScript array in preference to using new <code>Array(value1, value2)</code>.</li>
<li>Use <code>{ member: value, ... }</code> to create a JavaScript object; over <code>new Object()</code>.</li>
<li>Don't compare booleans to <code>true</code> or <code>false</code>. For example, write <code>if (ioService.offline)</code>. Compare objects to <code>null</code>, numbers to <code>0</code> or strings to <code>""</code> if there is chance for confusion.</li>
</ul>
<h2>Suggestions</h2>
<p>These guidelines are not hard and fast rules, but almost always a good idea. Please try to follow them.</p>
<ul>
<li>Be very careful about assignments that are also used in a boolean context, e.g. <pre>while (node = node.parentNode) { /* ... */ }</pre> or <pre>for (var i=0, item; item=array[i]; i++) { /* ... */ }</pre>This can be a common source of subtle bugs.</li>
<li>When a <code>switch</code> statement's <code>case</code> contains a body, and intentionally falls through to the next (with no <code>break</code>), add a comment like <code>// fall-through</code> to make it clear that this is intended.</li>
<li>Don't use <code>eval()</code> or equivalents if there is any other possible way to accomplish the goal.</li>
<li>Don't use <code>setTimeout()</code> or equivalents with string parameters, only function references. Generally avoid <code>setTimeout()</code> if at all possible &mdash; if not, comment why it was used.</li>
<li>Keep branches, and especially commits, topically relevant. Don't put code refactoring and new features together in one commit, or even together in a branch if at all possible.</li>
</ul>
</body>
</html>
Jump to Line
Something went wrong with that request. Please try again.