JavaScript Best Practices
This page as well as JavaScript Idioms and Gotchas is a compilation of JavaScript research by Douglas Crockford(adsafe.org, jslint.com), John Resig, Nicholas Zakas, Peter Michaux, Oliver Steele, and others:
Avoid the following:
Modifying the built-in functions (Object, Array, et al).
Use of global variables.
Use of eval in any of its forms.
Use of these commands:
apply eval
call new
callee prototype
caller source
clone this
constructor toSource
toString watch
Use of variable names starting with _.
Use of the [] subscript operator(bracket notation). This is because of a hole in Firefox.
Use of the window object within a function
Use of the alert statement for debugging
Use of code that has not been tested in jslint, minified, or gzipped
Best Practices
Use {} instead of new Object(). Use [] instead of new Array().
Use arrays when the member names would be sequential integers. Use objects when the member names are arbitrary strings or names.
Avoid the use of the comma operator except for very disciplined use in the control part of for statements. (This does not apply to the comma separator, which is used in object literals, array literals, var statements, and parameter lists.)
for (var i=0, j=9; i <= 9; i++, j--)
{
alert("a["+i+"]["+j+"]= " + a[i][j]);
}
In JavaScript blocks do not have scope. Only functions have scope. Do not use blocks except as required by the compound statements. Define all variables at the beginning of functions, including loop counters.
Avoid doing assignments in the condition part of if and while statements.
Remember that the last iteration of a for loop will increment the index before terminating, so it will end up being equal to the max condition plus one
It is almost always better to use the === and !== operators. The == and != operators do type coercion. In particular, do not use == to compare against falsy values(null, undefined, false, 0, “”).
Be careful to not follow a + with + or ++. This pattern can be confusing. Insert parentheses between them to make your intention clear.
total = subtotal + +myInput.value;
is better written as
total = subtotal + (+myInput.value);
so that the + + is not misread as ++.
The eval function is the most misused feature of JavaScript. Avoid it.
Do not use the Function constructor.
var multiply = new Function("a", "b", "return a + b");
Do not pass strings to setTimeout or setInterval.
Do not use the if statement to select one out of two values. This is what the ?: ternary operator is for.
Use if to select one of two actions to take following a condition.
var silent = privacy.checked ? 'on' : 'off';
Use the || operator to specify a default value for a variable
var value = v || 10;
Use the && operator to check for null before an assignment
var value = p && p.name;
Use nested functions to avoid the need for global variables
In all of the A Grade browsers, we should always write for-in statements in this form:
for (name in obj)
{
if (obj.hasOwnProperty(name) )
{
...
}
}
hasownProperty object method indicates whether an object has a specified property defined.
hasownProperty determines whether an object has the specified property as a direct attribute.
Unlike the in operator, it does not check down the object’s prototype chain.
The hasOwnProperty method is useful in making JavaScript’s objects act as general containers.
For example, suppose you are keeping a list of key words where each word is used as a key.
We can quickly determine if a word is in our list:
function check_word(word)
{
return !!words[word];
}
Unfortunately, the function can produce the wrong result if the word is “constructor” because there will be a constructor property in words’s prototype chain.
We can use hasOwnProperty to filter out the chain.
function check_word(word)
{
return words.hasOwnProperty(word);
}
One of the unfortunate consequences of the language having gone through multiple versions is that not every JavaScript environment provides the hasOwnProperty method.
IE 5.0 and Safari 1.3 do not. If your program has to run in those as well, then there is an older equivalent that is almost as good, in which we filter out function values.
for (name in obj)
{
if (typeof obj[name] !== 'function')
{
...
}
}
function check_word(word)
{
return typeof words[word] !== 'function';
}
We then loop over the array of words, and on each iteration we will match a word against the list.
if (myList[arrayOfWords[i]])
{
// A match!
}
So we won’t match “construct”. But we will match “hope”. Great.
Our code works. Or does it? This code will also match “constructor” even though “constructor” is not in our list. Why is this? It is because every object has “construct” member.
So we get a false positive.
Any member anywhere in the prototype chain can cause a false positive.
So how can we fix this?
JavaScript’s in operator is useless because it produces the same false positive.
We could take advantage of the fact that all of the values in myList are true by doing exact comparisons.
if (myList[arrayOfWords[i]] === true)
{
// A match!
}
That works. But suppose we want myList’s values to be functions which will be called when a key matches.
In that case, we can’t look for a known value, and
if (typeof myList[arrayOfWords[i]] === 'function')
{
// A match!
}
won’t work because myList.constructor is also a function. What we can do is explicitly reject keys that come from the prototype chain.
var word = arrayOfWords[i];
if (myList.hasOwnProperty(word) && myList[word])
{
// A match!
}
So the solution here is the same solution required to make for statements work correctly: the hasOwnProperty method.
If we use it to guard against unintended inheritance, then we can safely use JavaScript’s objects as general containers.
We can make JavaScript work correctly at the cost of a bit of ugliness in our code.
It is a nuisance, it is irritating, and it feels like a waste of time.
You could also say the same thing about washing your hands after using the restroom.
Do it anyway. Good hygiene is good for you. And your code.
Use clearInterval inside of the function that defines the setInterval call
Make sure timer functions have global scope or use this operator
Use relative or absolute positioning for elements that you want to animate
ex.
var animate = setInterval(function(){ anim_function(); }, speed);
if (homepage.test(this.location) )
{
move_text;
}
function ticker()
{
node.style.left = count + "px";
count++;
if (count > 600)
{
node.style.left = "0px";
}
}
Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.