JavaScript Development
This document exists to establish common practices among UConn developers, vendors, subcontractors, and affiliates writing JavaScript code for UConn projects. This standard benefits the Higher Education developers and Open Source communities, and the University of Connecticut. By adhering to strict development standards, we can enjoy the efficiencies of code sharing and code reuse. Developers should strive for compliance with the standards summarized in this document or as enforced by their respective project’s approvers.
JavaScript
JavaScript encompasses three areas, the core (ECMAScript ), the DOM (Document Object Model), and the BOM (Browser Object Model). (Zakas N. C., 2005)
While modern browsers all implement the core to the same specification, their implementation of the DOM and BOM may differ. JavaScript developers face a unique challenge in that their code must produce similar results across several disparate environments (or degrade gracefully).
For a visual overview of browser differences in the DOM, see Quirksmode.org .
Why We Need JavaScript
All modern browsers act as a host environment for JavaScript. Like a web server running PHP or Java, the browser performs the processing and execution of JavaScript on the client side. This allows developers to create modern web applications with rich interaction, animation, and fewer round trips to the server.
Why We Need JavaScript Standards
JavaScript’s loose typing and prototypal inheritance make it different from classical languages, like Java. This can frustrate new JavaScript developers who attempt to force classical patterns over proper JavaScript patterns. (Crockford, 2008)
Standards
Files
JavaScript files should have the .js file extension. While browsers do not require this extension, it helps other developers understand how an application’s components fit together.
Developers may ‘minify’ or compress JavaScript files for performance reasons but should not employ additional obfuscation techniques unless required by the project. As a general rule, confidential information should not appear in JavaScript files because they are text documents processed on the client’s computer and therefore insecure.
While not required, organization of JavaScript files into a separate directory also helps other developers find application components quickly.
External Files vs. Inline Code
Whenever possible, move large amounts of inline JavaScript to external files for maintainability and to take advantage of browser caching. Place all references to external files as well as inline code in the <HEAD> section of the document.<script src=”webjslint.js”></script>
Keep JavaScript unobtrusive by adding calls to previously defined functions using DOM methods. As often as possible, use advanced event registration methods over window.onload.function doSomething() {
}
function doSomethingElse() {
}
window.onload = doSomething;
// window.onload = doSomethingElse; this would overwrite call to doSomething
// instead use
window.onload = function () {
doSomething();
doSomethingElse();
}
// or create a reuseable function
// most libraries include an event handler
function addEvent(obj, evType, fn) {
if (obj.addEventListener)
else if (obj.attachEvent)
else
}
addEvent(window, ‘load’, doSomething);
addEvent(window, ‘load’, doSomethingElse);
Dynamic vs. Static Code
Avoid using another programming language to write JavaScript inline code. Untested conditions in the application can produce failed or invalid JavaScript. Eliminating this practice increases the potential for code reuse and reduces time spent testing and troubleshooting JavaScript.
Syntax
Developers and code approvers can use JSLint with the following settings to assist in the code review process:
- Strict white space (4 spaces)
- Allow one var statement per function
- Disallow undefined variables
- Disallow dangling _ in identifiers
- Disallow == and !=
- Disallow bitwise operators
- Disallow insecure . and [^…] in /RegExp/
- Require “use strict”; (used in full file review)
- Require Initial Caps for constructors
- Require parenthesis around immediate invocations
Or use quick configuration with the following string:
jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true
White-space and Semi-colons
While we can often remove optional whitespace and end-of-line semi-colons from JavaScript to reduce file, developers must preserve whitespace and proper punctuation in all source code for readability. Only use a systematic method for removing whitespace in production files, such as:
Comments
JavaScript uses the same comment syntax as Java. However, because the block comment character sequences (/*/) can appear in regular expressions, do not use them for inline code or outside of formal documentation sections. Instead, use the single-line comment (//)./
do not use inline
*/
// ok to use anywhere
Comment blocks (with the additional beginning *) should appear in external JavaScript files as documentation:/**
- Returns a guid associated with an object. If the object
- does not have one, a new one is created unless readOnly
- is specified.
* - @method stamp
- @param o The object to stamp
- @param readOnly
Unknown macro: {boolean}
if true, a valid guid will only be returned if the object has one assigned to it.
- @return
Unknown macro: {string}
The object’s guid or null
*/
Code Blocks
Enclose code blocks between { } characters with the starting brace at the end of the first line and the ending brace by itself after the last line. Indent all statements within the code block.”use strict”;
function codeBlock() {
alert(‘inside a code block’);
}
Line Length
Avoid lines over 80 characters long. Break up long lines of code after an operator to avoid copy/paste mistakes or parsing errors.function longLine() {
var str = “This string will need to continue ” +
“on the next line.”,
obj = {
property: “one”,
innerObj:
},
arr = [“one”, “two”, “three”,
“four”, “five”];
}
Patterns
Object References and Dereferencing
JavaScript never copies objects, it only creates multiple references.
As a method of avoiding errors and freeing up environment memory, dispose of objects by setting all references to null after you no longer need them.var oObject = new Object;
//do something with the object here
oObject = null;
Names
Names are used for statements, variables, parameters, property names, operators, and labels. Do not use the following words for names:
abstract, boolean, break, byte, case, catch, char, class, const, continue, debugger, default, delete, do, double, else, enum, export, extends, false, final, finally, float, for, function, goto, if, implements, import, in, Infinity, instanceof, int, interface, long, NaN, native, new, null, package, private, protected, public, return, short, static, super, switch, synchronized, this, throw, throws, transient, true, try, typeof, undefined, var, volatile, void, while, with.
Other identifiers to avoid:arguments, encodeURI, Object, String, Array, Error, isFinite, parseFloat, SyntaxError, Boolean, escape, isNaN, parseInt, TypeError, Date, eval, Math, RangeError, decodeURI, EvalError, ReferenceError, unescape, decodeURIComponent, Function, Number, RegExp, URIError
Variables must consist of a letter character followed by any combination of letters, numbers, or underscore. When possible, use camel notation (camel-case) to separate words:var a_variable_name = “bad”;
var _variable_name = “bad”;
var aVariableName = “good”;
Constructors (functions which return an object and make use of the new operator) must start with a capital letter.
Scope
Because JavaScript uses block syntax but does not provide block scope, developers must take special care to manage scope. For this reason, use only one var statement at the top of each function.
Web applications must minimize their use of the global namespace. Developers should assign application-specific functions and variables to an application namespace. This helps with code testing and troubleshooting by keeping code modular and reusable. This practice also reduces the chances of a namespace conflict when using an external library or framework.”use strict”;
var MyApp = undefined || MyApp; // define variable unless it exists
if (typeof MyApp === ‘undefined’ || !MyApp) {// create if needed
(function () {
var privateVar = “private”, // private variable
privateFunc = function ()
,
soonToBePublic = function ()
;
MyApp = {
init: function ()
,
config:
,
setup: function () {
},
getPrivate : soonToBePublic // private method now public
};
}());
}
Form Interaction
Due to a bug in earlier versions of IE, as a best practice, use reference the form and its elements rather than an element by ID.// use this
var myInput = document.forms“formname”.elements“inputname”;
// instead of this
var myInput = document.getElementById(“inputid”);
Tools
Code Validation
JSlint can help developers by quickly identifying errors and potential problems with either the online or offline version.
Browsers
Along with the previously mentioned JSlint , most modern browsers have script debuggers and consoles. Other browsers make use of add-ons to accomplish this task, like the very popular Firebug add-on for Firefox. See your browser’s documentation for enabling developer mode features.
Modern browsers raise more exceptions and prevent some “unsafe” JavaScript actions when developers implement the “use strict” feature. (Resig, 2009)
When developing for multiple browsers, check for method availability and possible pitfalls of using certain methods by using the Master Compatibility Tablehttp://www.quirksmode.org/dom/w3c_core.html.
Interactive Development Environment (IDE)
Syntax highlighting, proper spacing and formatting, and code block collapsing can all help speed the development process. Developers should use an IDE for JavaScript development like any other programming language.
Libraries
JavaScript libraries offer valuable tools for reducing development time and increasing performance—if used correctly. Use these guidelines for implementing a JavaScript library:
- Only use a library with the full source (not minified or compressed) code available
- Only use a library which is actively maintained
- Use the latest version of the library and apply security and bug patches when they are released
- Ensure support for all browsers required for the project
- Do not fork or modify the library files
- Do not override library methods
- Avoid shorthand naming, like $, as this can lead to namespace conflicts and cause confusion
Anti-patterns (Unnecessary Practices)
myElement.style.width = “20px”
Avoid setting CSS style attributes with JavaScript. Instead, create the proper CSS classes and apply or remove those classes.
document.write
This method is depreciated. Developers should use DOM methods to change the DOM.
<noscript></noscript>
A better approach involves including a ‘No JavaScript’ message in the application that is removed by JavaScript. If the user’s browser has no JavaScript or JavaScript is disabled, the message will appear.
href = “javascript:”, onclick = “javascript:”
Developers must use unobtrusive JavaScript. Add the necessary JavaScript enhancements to valid HTML through JavaScript DOM methods, not the HTML.
switch (without a default: statement)
Use the default segment of a switch statement to warn that a case ‘fell through’ the switch statement without satisfying one of the conditions. Otherwise, this common source of errors will lead to difficulties during troubleshooting.
onclick = “void(0)”
Suppress default actions with unobtrusive patterns (see above). Also, avoid the void operator as it always returns undefined, which holds no value.
var myObject = New Object();
Use the object literal notation: var myObject = {};
var myArray = New Array();
Use the array literal notation: var myArray = [];
document.all, document.layers, navigator.useragent
Browser sniffing causes more problems than it fixes. Detect for specific DOM methods instead.
// correct
function addEvent(obj, evType, fn) {
if (obj.addEventListener)
}
// incorrect
function addEvent(obj, evType, fn) {
if (obj.addEventListener())
}
with
Avoid using the with statement, it tends to obscure the true intent of a code block.
continue and break
Avoid using the continue and break statements, it can obscure the intended loop logic.
_myPrivateVariable
Attempts to indicate private variables with a leading underscore (or leading and trailing double underscore) can make developers complacent or confuse a variable’s true nature. Use the naming conventions described above and use a debugger to verify property privacy.
eval
Developers often use eval in lieu of proper object and subscript notation.
// use this
myvalue = myObjectmyKey;
// instead of this
eval(“myValue = myObject.” + myKey + “;”);
Malicious code can exploit eval. Developers should avoid eval and setTimeout (which can act like eval) for this reason.
== and != vs. === and !==
When using equality operators, choose === or !== over their counterparts as they also compare type and help preserve transitivity in variables. (Crockford, 2008)
” == ‘0’; //false
0 == ”; //true
0 == ‘0’; //true
false = ‘false’; //false
false == ‘0’; //true
false == undefined; //false
false == null; //false
null == undefined; //true
‘\t\r\n ‘ == 0; //true
New Boolean()
Avoid the Boolean class, instead use Boolean primitives, true and false.
try-catch Statement
Developers trying to apply their knowledge of classical languages often misuse the try-catch pattern and ultimately suppress important error information. For this reason, avoid try statements. Additionally, try (the catch part) and with statements add an object to the front of the scope chain making them less desirable for performance reasons. (Zakas N. , 2009)
References and Additional Reading
- Crockford, D. (2008). JavaScript: The Good Parts. Sebastopol, CA: O’Reilly Media.
- Koch, Peter-Paul (2009). Compatibility Master Table. Retrieved 1 4, 2010, from http://www.quirksmode.org/compatibility.html
- Murphey, R. (2009, 9 13). Using Objects to Organize your jQuery Code. Retrieved 10 15, 2009, from SlideShare:http://blog.rebeccamurphey.com/organize-your-jquery/
- Resig, J. (2009, May 21). ECMAScript 5 Strict Mode, JSON, and More. Retrieved October 15, 2009, from John Resig: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
- Zakas, N. C. (2005). Professional JavaScript for Web Developers. Indianapolis, Indiana: Wiley Publishing.
- Zakas, N. (2009, 6). Speed Up Your JavaScript. Retrieved 10 15, 2009, from SlideShare: http://www.slideshare.net/nzakas/speed-up-your-javascript