As a follow-up to "30 HTML and CSS Best Practices", this week, we'll review JavaScript! Once you've reviewed the list, be sure to let us know what little tips you've come across!
1. Use === Instead of ==
JavaScript utilizes two different kinds of equality operators: === | !== and == | != It is considered best practice to always use the former set when comparing.
"If two operands are of the same type and value, then === produces true and !== produces false." - JavaScript: The Good Parts
However, when working with == and !=, you'll run into issues when working with different types. In these cases, they'll try to coerce the values, unsuccessfully.
2. Eval = Bad
For those unfamiliar, the "eval" function gives us access to JavaScript's compiler. Essentially, we can execute a string's result by passing it as a parameter of "eval".
Not only will this decrease your script's performance substantially, but it also poses a huge security risk because it grants far too much power to the passed in text. Avoid it!
3. Don't Use Short-Hand
Technically, you can get away with omitting most curly braces and semi-colons. Most browsers will correctly interpret the following:
if(someVariableExists) x = false
However, consider this:
if(someVariableExists) x = false anotherFunctionCall();
One might think that the code above would be equivalent to:
if(someVariableExists) {
x = false;
anotherFunctionCall();
}
Unfortunately, he'd be wrong. In reality, it means:
if(someVariableExists) {
x = false;
}
anotherFunctionCall();
As you'll notice, the indentation mimics the functionality of the curly brace. Needless to say, this is a terrible practice that should be avoided at all costs. The only time that curly braces should be omitted is with one-liners, and even this is a highly debated topic.
if(2 + 2 === 4) return 'nicely done';
Always Consider the Future
What if, at a later date, you need to add more commands to this if statement. In order to do so, you would need to rewrite this block of code. Bottom line - tread with caution when omitting.
4. Utilize JS Lint
JSLint is a debugger written by Douglas Crockford. Simply paste in your script, and it'll quickly scan for any noticeable issues and errors in your code.
"JSLint takes a JavaScript source and scans it. If it finds a problem, it returns a message describing the problem and an approximate location within the source. The problem is not necessarily a syntax error, although it often is. JSLint looks at some style conventions as well as structural problems. It does not prove that your program is correct. It just provides another set of eyes to help spot problems."
- JSLint Documentation
Before signing off on a script, run it through JSLint just to be sure that you haven't made any mindless mistakes.
5. Place Scripts at the Bottom of Your Page
This tip has already been recommended in the previous article in this series. As it's highly appropriate though, I'll paste in the information.
Remember -- the primary goal is to make the page load as quickly as possible for the user. When loading a script, the browser can't continue on until the entire file has been loaded. Thus, the user will have to wait longer before noticing any progress.
If you have JS files whose only purpose is to add functionality -- for example, after a button is clicked -- go ahead and place those files at the bottom, just before the closing body tag. This is absolutely a best practice.
Better
<p>And now you know my favorite kinds of corn. </p> <script type="text/javascript" src="path/to/file.js"></script> <script type="text/javascript" src="path/to/anotherFile.js"></script> </body> </html>
6. Declare Variables Outside of the For Statement
When executing lengthy "for" statements, don't make the engine work any harder than it must. For example:
Bad
for(var i = 0; i < someArray.length; i++) {
var container = document.getElementById('container');
container.innerHtml += 'my number: ' + i;
console.log(i);
}
Notice how we must determine the length of the array for each iteration, and how we traverse the dom to find the "container" element each time -- highly inefficient!
Better
var container = document.getElementById('container');
for(var i = 0, len = someArray.length; i < len; i++) {
container.innerHtml += 'my number: ' + i;
console.log(i);
}
Bonus points to the person who leaves a comment showing us how we can further improve the code block above.
7. The Fastest Way to Build a String
Don't always reach for your handy-dandy "for" statement when you need to loop through an array or object. Be creative and find the quickest solution for the job at hand.
var arr = ['item 1', 'item 2', 'item 3', ...];
var list = '<ul><li>' + arr.join('</li><li>') + '</li></ul>';
I won’t bore you with benchmarks; you’ll just have to believe me (or test for yourself) - this is by far the fastest method!
Using native methods (like join()), regardless of what’s going on behind the abstraction layer, is usually much faster than any non-native alternative.
- James Padolsey, james.padolsey.com
8. Reduce Globals
"By reducing your global footprint to a single name, you significantly reduce the chance of bad interactions with other applications, widgets, or libraries."
- Douglas Crockford
var name = 'Jeffrey';
var lastName = 'Way';
function doSomething() {...}
console.log(name); // Jeffrey -- or window.name
Better
var DudeNameSpace = {
name : 'Jeffrey',
lastName : 'Way',
doSomething : function() {...}
}
console.log(DudeNameSpace.name); // Jeffrey
Notice how we've "reduced our footprint" to just the ridiculously named "DudeNameSpace" object.
9. Comment Your Code
It might seem unnecessary at first, but trust me, you WANT to comment your code as best as possible. What happens when you return to the project months later, only to find that you can't easily remember what your line of thinking was. Or, what if one of your colleagues needs to revise your code? Always, always comment important sections of your code.
// Cycle through array and echo out each name.
for(var i = 0, len = array.length; i < len; i++) {
console.log(array[i]);
}
10. Embrace Progressive Enhancement
Always compensate for when JavaScript is disabled. It might be tempting to think, "The majority of my viewers have JavaScript enabled, so I won't worry about it." However, this would be a huge mistake.
Have you taken a moment to view your beautiful slider with JavaScript turned off? (Download the Web Developer Toolbar for an easy way to do so.) It might break your site completely. As a rule of thumb, design your site assuming that JavaScript will be disabled. Then, once you've done so, begin to progressively enhance your layout!
11. Don't Pass a String to "SetInterval" or "SetTimeOut"
Consider the following code:
setInterval(
"document.getElementById('container').innerHTML += 'My new number: ' + i", 3000
);
Not only is this code inefficient, but it also functions in the same way as the "eval" function would. Never pass a string to SetInterval and SetTimeOut. Instead, pass a function name.
setInterval(someFunction, 3000);
12. Don't Use the "With" Statement
At first glance, "With" statements seem like a smart idea. The basic concept is that they can be used to provide a shorthand for accessing deeply nested objects. For example...
with (being.person.man.bodyparts) {
arms = true;
legs = true;
}
-- instead of --
being.person.man.bodyparts.arms = true; being.person.man.bodyparts.legs= true;
Unfortunately, after some testing, it was found that they "behave very badly when setting new members." Instead, you should use var.
var o = being.person.man.bodyparts; o.arms = true; o.legs = true;
13. Use {} Instead of New Object()
There are multiple ways to create objects in JavaScript. Perhaps the more traditional method is to use the "new" constructor, like so:
var o = new Object();
o.name = 'Jeffrey';
o.lastName = 'Way';
o.someFunction = function() {
console.log(this.name);
}
However, this method receives the "bad practice" stamp without actually being so. Instead, I recommend that you use the much more robust object literal method.
Better
var o = {
name: 'Jeffrey',
lastName = 'Way',
someFunction : function() {
console.log(this.name);
}
};
Note that if you simply want to create an empty object, {} will do the trick.
var o = {};
"Objects literals enable us to write code that supports lots of features yet still make it a relatively straightforward for the implementers of our code. No need to invoke constructors directly or maintain the correct order of arguments passed to functions, etc." - dyn-web.com
14. Use [] Instead of New Array()
The same applies for creating a new array.
Okay
var a = new Array(); a[0] = "Joe"; a[1] = 'Plumber';
Better
var a = ['Joe','Plumber'];
"A common error in JavaScript programs is to use an object when an array is required or an array when an object is required. The rule is simple: when the property names are small sequential integers, you should use an array. Otherwise, use an object." - Douglas Crockford
15. Long List of Variables? Omit the "Var" Keyword and Use Commas Instead
var someItem = 'some string'; var anotherItem = 'another string'; var oneMoreItem = 'one more string';
Better
var someItem = 'some string',
anotherItem = 'another string',
oneMoreItem = 'one more string';
...Should be rather self-explanatory. I doubt there's any real speed improvements here, but it cleans up your code a bit.
17. Always, Always Use Semicolons
Technically, most browsers will allow you to get away with omitting semi-colons.
var someItem = 'some string'
function doSomething() {
return 'something'
}
Having said that, this is a very bad practice that can potentially lead to much bigger, and harder to find, issues.
Better
var someItem = 'some string';
function doSomething() {
return 'something';
}
18. "For in" Statements
When looping through items in an object, you might find that you'll also retrieve method functions as well. In order to work around this, always wrap your code in an if statement which filters the information
for(key in object) {
if(object.hasOwnProperty(key) {
...then do something...
}
}
As referenced from JavaScript: The Good Parts, by Douglas Crockford.
19. Use Firebug's "Timer" Feature to Optimize Your Code
Need a quick and easy way to determine how long an operation takes? Use Firebug's "timer" feature to log the results.
function TimeTracker(){
console.time("MyTimer");
for(x=5000; x > 0; x--){}
console.timeEnd("MyTimer");
}
20. Read, Read, Read...
While I'm a huge fan of web development blogs (like this one!), there really isn't a substitute for a book when grabbing some lunch, or just before you go to bed. Always keep a web development book on your bedside table. Here are some of my JavaScript favorites.
Read them...multiple times. I still do!
21. Self-Executing Functions
Rather than calling a function, it's quite simple to make a function run automatically when a page loads, or a parent function is called. Simply wrap your function in parenthesis, and then append an additional set, which essentially calls the function.
(function doSomething() {
return {
name: 'jeff',
lastName: 'way'
};
})();
22. Raw JavaScript Can Always Be Quicker Than Using a Library
JavaScript libraries, such as jQuery and Mootools, can save you an enormous amount of time when coding -- especially with AJAX operations. Having said that, always keep in mind that a library can never be as fast as raw JavaScript (assuming you code correctly).
jQuery's "each" method is great for looping, but using a native "for" statement will always be an ounce quicker.
23. Crockford's JSON.Parse
Although JavaScript 2 should have a built-in JSON parser, as of this writing, we still need to implement our own. Douglas Crockford, the creator of JSON, has already created a parser that you can use. It can be downloaded HERE.
Simply by importing the script, you'll gain access to a new JSON global object, which can then be used to parse your .json file.
var response = JSON.parse(xhr.responseText);
var container = document.getElementById('container');
for(var i = 0, len = response.length; i < len; i++) {
container.innerHTML += '24. Remove "Language"
Years ago, it wasn't uncommon to find the "language" attribute within script tags.
<script type="text/javascript" language="javascript"> ... </script>
However, this attribute has long since been deprecated; so leave it out.
That's All, Folks
So there you have it; twenty-four essential tips for beginning JavaScripters. Let me know your quick tips! Thanks for reading. What subject should the third part in this series cover?
- Follow us on Twitter, or subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.
Related Posts
Check out some more great tutorials and articles that you might like
Plus Members
Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.










User Comments
( ADD YOURS )Marc June 16th
first! … lol always wanted to do that… nice article
( )Simbioziz July 1st
Такая же история! Тот кто ищет тот всегда найдет!) Thanks Jeffrey
( )Myfacefriends June 16th
another great tuts! thanks jeff!
( )Diogok June 16th
Awesome practices.
( )HB June 16th
Example #11 is still passing a string… instead of setInterval(”someFunction()”, 3000); it should be setInterval(someFunction, 3000); That’s now passing a function reference instead of a string.
Other than that, excellent tips and reminders for beginners and experts alike.
( )Jeffrey Way June 16th
Whoops.
( )James June 16th
Also, on number 11, the first argument should be wrapped in quotes to illustrate your point:
Instead of:
document.getElementById(’container’).innerHTML = ‘My new number: ‘ + i
I think you meant:
“document.getElementById(’container’).innerHTML = ‘My new number: ‘ + i”
( )Crysfel June 16th
I agree! also you can use an anonym function
setInterval(function(){
( )//do your stuff here
},3000);
Jeffrey Way June 16th
Thanks for finding all of my little typos, guys. Post updated.
dmoena June 16th
Also, one big problem (when you don’t know how to do it) is to pass some parameters to the delayed function.
Fortunatelly, you can you do this by simple using an anonym function to encapsulate your target function. This means
setInterval(function(){
targetFunction(param_1, param_2);
},3000);
done!
( )Timothy June 16th
Nice list. Would be nice to see something about anonymous functions, prototyping, native objects and the fact that everything in JavaScript is an object.
( )Joseph Pecoraro June 16th
You mention some good topics. They may not be beginner topics but they are certainly required learning for advancement with JavaScript. Also, not everything in JavaScript is an object. Literal numbers for instance are not objects. Take the following example:
5.toString() => Produces a parse error
(new Number(5)).toString() => works correctly
Ruby is an example of a language where nearly everything is an object. You can call methods directly on literal numbers, etc.
( )Karl Swedberg June 16th
You’re right, literal numbers are primitives. However, you don’t need (new Number(5)) to get it to work correctly. Instead, try this:
(5).toString() // => works correctly
Joseph Pecoraro June 16th
Ahh, excellent point Karl! I honestly didn’t know that, but it makes a lot of sense. The same is true for calling an anon function. Thanks!
Jermaine Hercules June 16th
Greate tips, I found this very helpful seems as how im just starting to learn javascript.
( )Shane June 16th
Good list – some of the things apply to multiple languages (not a criticism!)
I find very few people adopt number 9
( )Meshach June 16th
Nice compilation, thanks Jeffrey.
( )Gilberto Ramos June 16th
thanks Jeffrey!!
( )Nicolas June 16th
Like it, thanks it was a good reading.
( )Marc Grabanski June 16th
On #24 you can eliminate the type attribute as well.
( )“There is no need to use the language or type attributes. It is the server, not the script tag, that determines the MIME type. ”
( http://javascript.crockford.com/code.html ).
Michael Irwin June 16th
To validate with XHTML Strict, you need to have the type attribute.
( )Joseph Pecoraro June 16th
In HTML4 the type attribute is required (which carries over to XHTML like Michael Irwin mentioned):
http://www.w3.org/TR/REC-html40/interact/scripts.html#edef-SCRIPT
In HTML5 the type attribute will default to “text/javascript” and can be left out:
http://dev.w3.org/html5/spec/Overview.html#script
As for removing the type attribute, I don’t actually see any mention of using the MIME type in the HTML4 spec. I may have missed it or it may just be a browser convention developed over the last 10 years. But for now, it might be better to just keep it in. How many servers do you know that are serving JS with the correct MIME type anyways? =)
( )Zac Vineyard June 16th
Excellent!
( )Nick June 16th
Excellent Post!! Learned a few new tricks!!
( )Brenelz June 16th
I will try for some bonus points
6. Declare Variables Outside of the For Statement
I think your example can be made faster by assigning the HTML to a variable… and then assigning the innerHTML outside of the loop. This way you are only injecting the code into the DOM once!
( )Jeffrey Way June 16th
Good. Got a code snippet for everyone?
( )Brenelz June 16th
Here is a snippet for everybody:
var container = document.getElementById(’container’);
( )var result = ”;
for(var i = 0, len = someArray.length; i < len; i++) {
result += ‘my number: ‘ + i;
console.log(i);
}
container.innerHtml = result;
Bernhard Häussner June 16th
Here is a snippet using #7 and #14:
var container = document.getElementById(’container’);
var result = [];
for(var i = 0, len = someArray.length; i < len; i++) {
result.push( ‘my number: ‘ + i);
console.log(i);
}
container.innerHtml = result.join();
(This might not be faster in Firefox 3 since they’ve optimized sting appending. )
And I think you may have to put “var” in front of len, don’t you? (Don’t know how for in JS should behave but in PHP you had)
James Pearson June 16th
Number 6, better still:
var container = document.getElementById(’container’);
var iArrayLength = someArray.length;
for(var i = 0, len = iArrayLength; i < len; i++) {
container.innerHtml += ‘my number: ‘ + i;
console.log(i);
}
Saves the cost of calculating the length of someArray on each pass of the loop.
Where do I claim my bonus points?
( )Jeffrey Way June 16th
We already did that in the “Better” example.
( )Jamie Rytlewski June 16th
No you didn’t. Look at his and look at your better. Above has the length figured out before the loop.
Joseph Pecoraro June 16th
James and Jamie: It seems you are either confusing the 3 different sections of the for loop or not noticing the comma in the first section.
Jeffrey’s example for loop is:
for(var i = 0, len = someArray.length; i < len; i++) { … }
1. This declares (i=0) AND (len=someArray.length) due to the comma separated list. It does this only once before the loop starts. See #15 for the same concept just spread out over multiple lines.
2. The only comparison for each loop iteration is (i<len)
3. The post loop section increments i as expected after each iteration.
Walter Wimberly June 16th
var container = document.getElementById(’container’);
for(var i = someArray.length – 1; i–; ) {
container.innerHtml += ‘my number: ‘ + i;
console.log(i);
}
If it doesn’t matter that you are going through the array backwards, of course if breaks another rule above about using === and !==, but what the hey…
For those who’ve never seen it – it inits your i to the size of the array, then counts backwards till you reach 0, which approx. eqs. false. You combine the test with the modify, have one less assignment at initialization, and your assignment is local, so your saving on accessing the memory stack too compared to assigning len outside of the loop
Alexandre Morgaut June 18th
Points to know :
– in JavaScript, variables have no block scope,
– affect a value to innerHTML call a HTML parse processus. The parsing is quick, but the call to the parser takes time. Manipulation of text is quicker in local variable
– think that JavaScript often transtype variable, so try to help it to do it less often when possible
– Good Parts in JSLint :
– disallow the use of ++ and –
– recommend the use of one only var for each scope
- array.join is quick on an already defined array, but you loose part of the benefit if you have to construct it before with some array.push
My proposal is then :
// use a single var
var len, i, iStr, result;
// if it hasn’t been done before create a fake console for when it’s not defined
window.console = window.console || {log: function(){}};
// here initialization might have been done at the declaration line (var),
// but it’s a good thing to initialize it for each for loop
// because you can’t always presume these variable hasn’t already been used
// note that the use of += also allow to easily modify the step of the loop
for (i = 0, len = someArray.length, result = ”; i < len; i += 1) {
// console.log and result will need to use i as a string
// for only two transtyping it might not be worth but think about it
iStr = String(i);
result += ‘my number: ‘ + iStr;
// with such simple code, the console.log should be called outer of the loop
// using another local variable
// note that i is
console.log(iStr);
}
// you don’t need to store the DOMElement in a local var anymore
document.getElementById(’container’).innerHTML += result;
// if you’re sure you won’t need result anymore you can delete it
( )// too free memory (i and len doesn’t use as much memory)
delete result;
Muhammad Adnan June 16th
great tut jeff !
( )Greg Ferrell June 16th
Thank you deeply for #24. People still do this all the time and it irks me to no end.
( )Reed June 16th
I had read in a lot of places that Array.join() is the fastest way to do string building, but eventually I did some more research and some benchmarking of my own, I’m really not so sure it is.
First, it depends A LOT on the browser. IE and Firefox have opposite strengths between array.join and the string concatenation operator.
It also depends on several variables like the number of iterations and the length of the strings being concatenated.
If you don’t have all the data in hand up front, and need to use array.push(), just so you can use array.join() at the end, this can end up being much, much slower.
In the end, string concatenation is really fast for most uses, so I’m wary of the suggestion that people not use it.
( )Joseph Pecoraro June 16th
Reed, I totally agree with you. I’m glad someone else brought this up besides me. I’ve done plenty of benchmarking on this and it depends on so many different factors: the number of elements being concatenated, the length of the strings being concatenated, the browser you’re using, how you would be adding elements to the array (push, [idx], unshift) and even more reasons.
Ultimately, unless you are building an extremely large string (with more then 1000 concatenations) it makes little difference. I would recommend taking the approach that is more readable or maintainable in your specific situation.
( )Mark June 16th
I also agree. I tested string concat and a so-called `StringBuilder’ and found string concat was faster in FF. I iterated a for loop thousands of times and each time took the current `i’ and added it to the dynamic string. String concat won. My StringBuilder func. was my attempt to make .NET’s StringBuilder in JavaScript: create a StringBuilder object with an optional string argument then call .Append(string here) on it to add to it. That would push to the internal array. Then when done at the end, call .ToString() on the object to join the array elements. I think I’ll stick to using `+=’ too.
( )Dan Wellman June 16th
Great article, I’d like to add to number 3 – only use if statements if necessary, use the conditional ternary instead, e.g.
don’t use:
if (a > b) {
//do something
}
but use:
(a > b) ? //do something : null ;
(obviously that comment in the above example would kill it, it’s just for the purpose of the example!)
The ternary can even nest so most if…else loops can be replaced as well. Like with number 15, you may not see any real performance gains, but the code is much neater
For number 6 I’d be tempted to move the len variable out of the for construct as well and use:
var container = document.getElementById(’container’),
len = someArray.length;
for(var i = 0; i < len; i++) {
( )container.innerHtml += ‘my number: ‘ + i;
console.log(i);
}
Jeffrey Way June 16th
Actually – I’m glad you brought up the point about moving the “len” variable out of the construct.
I’m wondering if there are any speed improvements with this method? Has anyone checked?
( )Joseph Pecoraro June 16th
I wrote a brief benchmark. Maybe someone can put a different spin on the way I attacked it:
http://gist.github.com/130774
My results were different between Safari/Webkit and Firefox 3.5. My results also differed if I swapped whichever benchmarking function runs first, I’m wondering if that is an indication of some JIT on the part of the javascript interpreters.
My suggestion would be to declare len outside of the for loop if you intend to use the len for another purpose as well. Otherwise keep the scope of the variable small and out of the way.
Walter Wimberly June 16th
It will make the len not being in the local stack of variables for the loop – (so some browsers more than others). JS looks in the closest variable stack, then the next, then the next, until it hits the global and can go no further – each time it jumps into a different memory space, it gets slower for repeated access – such as a loop test. Therefore, unless it is needed else where, put it in the initialization of the loop for speed.
tmack June 18th
> don’t use:
>
> if (a > b) {
> //do something
> }
>
> but use:
>
> (a > b) ? //do something : null ;
Your goal is obviously not readability.
( )James June 16th
Great list Jeffrey!
– “As you’ll notice, the indentation mimics the functionality of the curly brace”
Just to add a little explanation to this. IF statements are constructed in the following way:
if ([expression]) [statement]
If the expression evaluates to true then the statement is run. The good practice you mention involves surrounding multiple statements with curly braces, thus producing a “statement block” – a statement block is effectively a single statement containing any number of additional statements. Statement blocks are rarely seen as a construct in their own because they’re rarely useful on their own – you’ll normally only use them with a native language construct like with() or if() of for().
On another note, I’m glad that you put the advice about equality operators as #1. I really can’t stress the importance of this enough. People just don’t realise that doing this:
if (val == null) {…}
Is effectively the same as:
if (val === null || val === false || val === “” || val === 0 || val === undefined) {…}
( )Sean Sumido June 16th
Tip #3 reaction: Are you sure? Omitting { } is fine?
For me, I wouldn’t understand th logic if if I am going to remove the { and }
And I don’t take a risk bcause it might cause any errors and its hard for me not to use { } in IF (no ELSE) statement.
Guys, what do you think about it? do you think it would be ok to remove it? do you practice the traditional way (like putting {} ) or new-school way ?
( )Jeffrey Way June 16th
Did you read the whole tip? I recommended that you never omit them.
( )Jeremy June 16th
Nice list. A few things I’d add.
Decrementing over a large array or collection in is faster than incrementing.
for (var i = someBigArray.length – 1; i >= 0; i–) {
processElement(someBigArray[i]);
}
Use object literals instead of new Object();
var obj = {};
Use innerHTML when making many changes to the DOM. Not only is it less code, but it executes native, compiled code that builds the DOM structure and appends it to the DOM.
el.innerHTML = “Hello, World”;
( )Jeremy June 16th
And I need to proofread my comments before posting them. The above for loop should be:
for (var i = someBigArray.length – 1; i >= 0; i–) {
( )processElement(someBigArray[i]);
}
Jeremy June 16th
Sigh, nevermind
Dario Gutierrez June 16th
The number 5 is cool, I never used the scripts in that part of the page. Excellent tips.
( )max June 17th
#5 is a bad practice, imho
( )Kevin Choppin June 16th
Yet another great tuts post!
Thanks Jeff
( )Miguel June 16th
you can improve that for loop by replacing the coma after
var i = 0 with a semicolon so that this actually works.
so instead of
” (var i = 0, len = someArray.length; i < len; i++) ”
make it
“(var i = 0; len = someArray.length; i < len; i++)”
( )Jeffrey Way June 16th
Nope..
( )Miguel June 16th
nv mind I was looking at it wrong
( )ahh June 16th
thanks ,i didn’t understand any tip,because i haven’t start JS yet,your advice
( )the best way to start JS (Pls help !)
Benjamin Reid June 17th
If JS is really boggling your noggin, look @ http://jquery.com/
( )Allen Varney June 16th
I’m not seeing #16.
( )Jeremy June 16th
I don’t, either.
( )Vishal June 24th
#16 is below:
Always count your list twice before actually publishing it! …;-)
Ant June 16th
Thanks for tip № 21.
( )david June 16th
var container = document.getElementById(’container’),
len = someArray.length,
result = ”;
for(var i = 0; i < len; i++) {
( )result += ‘my number: ‘ + i;
console.log(i);
}
container.innerHtml = result;
david June 16th
var container = document.getElementById(’test’);
var result = ”;
for (i in someArray) {
result += ‘my number: ‘ + i;
console.log(i);
}
container.innerHTML = result;
This also works but on my tests runs about the same speed (FF3 on Ubuntu).
( )Brian Crescimanno June 16th
Do not iterate over arrays using for…in.
https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Statements/For…in
Brian Crescimanno June 16th
Close…but if you want to squeeze even more out of it:
var len = someArray.length,
result = “”;
for(var i=0; i<len; i++){
result += “my number: ” + i;
if(console){ console.log(i); }
}
document.getElementById(”container”).innerHTML += result;
Couple of things here:
1. For this block (outside the context of anything else) there’s no reason to store the container element in a variable–we only use it one time.
2. Never assume console exists–you need to check for it otherwise you wind up with errors in IE.
( )david June 16th
And another much faster method (though may not work on all browsers).
var container = document.getElementById(’test’),
result = ”;
function doIt(element, index, array) {
result += ‘my number: ‘ + index;
}
someArray.forEach(doIt)
( )container.innerHTML = result;
david June 16th
In the above loops console.log takes up 98% of the time. While this is not exactly the same the result is very similar and runs in 3ms instead of 185ms.
var result = ”;
function doIt(element, index, array) {
result += ‘my number: ‘ + index;
}
someArray.forEach(doIt)
document.getElementById(’test’).innerHTML += result;
console.log(someArray.join(’,'));
david June 16th
And in jQuery… I think I have to much time on my hands…
$.each(someArray, function(i, n){
$(’#test’).append(’my number: ‘ + i);
console.log(i);
});
Slow but so pretty!
( )Karl Swedberg June 16th
One more addition to #11:
Rather than pass a reference to a function as the first argument of setTimeout/setInterval, you can use an anonymous function:
setTimeout(function() {
( )// do something
}, 1000);
Joseph Pecoraro June 16th
One thing I had hoped would be on here would be the differences between parseInt() and Number() and common problems people run into.
parseInt(str, [radix]) – where radix is the base you wish to convert the string to.
Javascript number literals have support for octal and hex. For instance numbers starting with “0″ are octal. 011 is octal for 9. Those starting with “0x” are hex. 0×10 is hexadecimal for 16. parseInt reads values in the string up until the first invalid character for the number its parsing (this is dependent on the radix). This allows you to do the following:
parseInt(”12eggs”) => 12
However a common mistake for beginners is that they don’t provide a radix and get unexpected results. For instance take a date string such as “08-08-2009″. Trying to convert the string might baffle you:
parseInt(”08″) => 0
parseInt(”08″,10) => 8
The first case is correct behavior of parseInt(). The 0 at the start puts parseInt into octal mode, and 8 is invalid in octal. Therefore this is just like the “eggs” case where the letters were invalid in base 10, because “8″ is invalid in base 8 (0..7). I’d recommend always specifying the radix unless you are sure you want to allow octal and hex numbers with parseInt.
I’ll be brief with Number(). This provides developers with the advantage of failing if you really expect a string to be a raw number and get anything except a pure number, parses into base 10, and can convert Date objects to numbers:
Number(”12eggs”) => NaN
Number(”0010″) => 10
Number( new Date() ) => 1245173237669
Cheers.
( )James June 16th
A quicker way of casting certain types into their numerical form is by prefixing them with the “unary plus” operator:
+”12eggs” => NaN
( )+”0010″ => 10
+new Date() => 1245173237669
Karl Swedberg June 16th
Ha! James, you must have posted your comment while I was still typing mine! You win this round.
Karl Swedberg June 16th
Nice description of the differences between parseInt() and Number()!
Another, simpler, way to convert to a number is to use the unary “+” operator:
+”12eggs” // NaN
( )+”0010″ // 10
+new Date() // 1245178436214
James June 16th
@Karl, lol! It’s like one mind!
Joseph Pecoraro June 16th
Neat trick guys. I hadn’t known about that. Just be careful you don’t actually use the non-unary plus operator; you might not get what you’d expect:
1+”1″ => 11
Otherwise, this trick is pretty useful. Thanks!
( )Binny V A June 16th
I would add ‘Use a Library’.
( )Jack F June 16th
Depends what you need to achieve really. If it’s simple things, I would use Javascript. But if I was wanting to do drag+dropping/animations etc I would plump for a library (my personal preference would be jQuery).
( )larry ruckman June 16th
Nice list of useful information!
( )Asrar June 16th
Great article! Also, instead of doing:
if (!amount) {
amount = 1;
}
you can use shorthand like this:
amount = amount || 1;
( )tbela99 June 16th
if amount is undefined you’ll get an error, use amount = window.amount || 1 is safer
( )tbela99 June 16th
… in that case
tbela99 June 16th
and I love mootools!
James June 16th
No, you won’t get an error. If “amount” is “undefined” then the value “1″ will be assigned to it….
tbela99 June 16th
use an editor like netbeans to clean your code from unused vars, arguments, etc…
( )João Pedro Pereira June 16th
Nice, the firts article that I bookmarker related with JavaScript tips!
( )I think that you could talk about OOP with JavaScript. I wrote some articles related to JavaScript OOP in Portuguese:
http://joaopedropereira.com/blog/2009/03/14/js-oop-conceitos-basicos/
http://joaopedropereira.com/blog/2009/01/13/javascript-oop-1/
cancel bubble June 16th
Take advantage of JS libraries to handle cross browser problem areas like event handling, ajax.
Indent your code consistently.
Declare all variables before using them.
Always use {} for if statements, even if they’re one-liners
If you make calls to long namespaces, declare a var pointing to it
( )foo.bar.baz = { whatever… }
var baz = foo.bar.baz
Ed June 16th
Thanks!!!
Great Tut!
( )Simon June 16th
Thanks Jeffrey, always a pleasure to read your articles !
( )And the comments are damn interesting too, I already wrote some tips down on a post-it deep behing the eyes
Greg June 16th
Great post, I love it!!
( )- Greg
kreativeKING June 16th
More Efficient way
var container = document.getElementById(’container’);
var i = 0;
var len = someArray.length;
for(i, i < len; i++)
( ){
container.innerHtml += ‘my number: ‘ + i;
console.log(i);
}
Adrian June 16th
And you could make that even more efficient using #15.
( )Fernando Emmanoel Borba June 16th
Great post! Even for an advanced programmer.
( )drinkthere June 16th
God Like
( )Michael June 16th
Wow! Perfect timing – thanks a lot!
( )Rata June 16th
Excellent hints even for a beginner like me
Thanks!
Kind Regards
( )Rata
Aaron June 16th
Nice post. Most advice I was already following, thankfully, but when it comes to the Object protoype function “hasOwnProperty”, why would this function skip over function data and process non function data only?
I have the book “JavaScript: The Good Parts” by Crockford, and it doesn’t answer my question.
I searched the web but there doesn’t seem to be a lot of accurate info around the function.
Any ideas anyone?
( )Cody June 16th
Thanks for the JavaScript Tips!
( )henry June 16th
thanks for this
( )Dave Poon June 16th
Another great post from Nettuts!
( )It refreshes my mind,
and clear some of my questions!
Thanks.
Kivlor June 16th
Great Tutorial.
Maybe a PHP edition of the “Best Practices for Beginners” next??
( )Swapnil Sarwe June 16th
Hey nice tips, nice to know that i am following almost half of them.
Like using {} for empty objects, using JSLint, using [] for array, always making use of {} for conditions , love to use raw JS try to implement things in raw JS which people are using as plugins with jQuery, using === and few more….
Thanx to James Padolsey and Douglas Crockford for gr8 inspiration.
Love to watch video of presentations of Douglas Crockford and other JS videos from YUI Theatre (Go thru them, they are nice and informative). If you are new they are quiet helpful.
Where is 16 ??
( )Russ Back June 17th
Great article – thanks. Just a question on declaring Objects and Arrays. What’s the issue with new Object{} as apposed to object literals? I’ve tended to use the former as it’s more consistent with ActionScript and therefore easier to switch between the two. Be good to understand why {} and [] are best practice though.
( )Henrik Hjelte June 17th
About nr 9. Commenting code. If you feel the need to comment the code as you do, it is a sign that you need refactoring. I’d suggest do one or two of this instead:
A. Put it in a good named function. An added bonus is that it shows up in for example the Firebug profiler. In your case the function could be called logArray or printArray or debugLogArray. That makes the comment obsolete, and the code self-documenting.
B. Reduce the trickiness. The example you have is quite simple, but I think the for loop is verbose. There are two new variables and four or so expressions. Why not use some library and a function for iterating over arrays?
( )I’d think this is clearer and less bug prone:
somelib.each(array, console.log)
Replace somlib and each with your own choice.
kel June 17th
Yes – commenting a for loop that outputs a string on each iteration isn’t necessary and adds verbosity and whatnot. Comments aren’t to explain what is happening (necessarily). They are chiefly to explain *why* you did something (exceptions abound). Furthermore, I prefer them in conversational tone: “next, we need to be sure that this hasn’t already been set….” something like that. That tone will bring comfort to those who follow you and digest your code.
( )Jeffrey Way June 17th
Yes – I’m aware of that. This was just a simple example to demonstrate the idea. Obviously, commenting a simple for-loop isn’t necessary.
Gerrit June 17th
Nice list!
( )You could also combine #8 and #21 to avoid global variables by putting all code that goes together in the same function scope:
(function(){
var name = ‘Jeffrey’;
var lastName = ‘Way’;
var doSomething = function() {…} ;
console.log(name); // Jeffrey — not window.name
})(); // semi-colon, remember #17
emonweb June 17th
Thanks author. Some gr8 tips. anyway 16 is missing.
( )Ben June 17th
I’d say, a good advice for beginners would be to not go too fast into frameworks like jQuery. Because it might lead to confusion.
( )Nick Tulett June 17th
#2
For example – to avoid using eval for dynamic function names
Eval
// Call the function
result = eval(”test” + i + “();”);
Not Evil
( )// Call the function
result = window["test" + i]();
DemoGeek June 17th
Avoiding the “new” keyword…any other obvious reasons other than that it reduces some verbose typing? It’s pretty much engraved in mind from those old OOP days to use “new”. Wanted to see if it’s worth to get rid of that notion from mind.
( )Thantos Kalev June 17th
As usual, excellent advice. As mundane as #24 sounds, I still do it…Old habits die hard!
( )Yigit Ozdamar June 17th
Great list! Thank you dude.
( )Jonathan Garcia June 17th
Thanks, very helpful and informative, picked up a few things I never even thought of.
( )Montana Flynn June 17th
Amazingly helpful! Thanks a lot I learned so much.
( )Mike June 17th
absolutely love it!
( )Mortaza Doulaty June 18th
Very helpful, great tips, thanks!
( )Teachmeter June 18th
I’m new to JS but shouldn’t there be a name = ‘name’ instead of name: ‘name’? I don’t know for sure but just want to ask it.
( )Teachmeter June 18th
I’ve meant the #13 paragraph
( )Kramii June 18th
#7 is brilliant – I would never have thought of it.
I’m not sure I see the benefit of #15, though.
( )Coby June 18th
where is #16? should it not be “23 javascript best practices for beginners?”
( )Coby June 18th
great tips by the way!!!
( )Maryam June 18th
tnx
( )Brien June 18th
Extremely helpful post. I’m surprised there were this many comments without a grammar cop busting you on #22: “…can always…” Those two words are mutually exclusive. I something can happen, it doesn’t always happen.
( )mr mister June 18th
I knew most of them already!!!!
( )kareemkarawia June 18th
nice tutorial
( )thanks alot
juergenriemer June 18th
If you have to comment your code it is time to refactor.
( )Extract methods an name them properly, have a good controller function and no need for comments. The only place I would use comments is if I have complex algorithms or complex regular expressions.
Magnus June 18th
Number 16 is missing.
( )Bob June 18th
16. Don’t assume that document elements exist.
Bad:
document.getElementById( ‘myLabel’ ).innerHTML = ‘Some wonderful text’;
Better:
var element = document.getElementById( ‘myLabel’ )
( )if ( element && ( ‘innerHTML’ in element ) ) {
element.innerHTML = ‘Some wonderful text’;
}
Bob June 18th
#6 should really be worded as “Define variables outside of For Statement”
Declaring is not the same as defining.
also…
Use local variables in For Statement is really important.
For example, in #18, you have:
for(key in object) {
instead of:
for(var key in object) {
which means that key is a global variable.
In #19, you have:
for(x=5000; x > 0; x–){}
instead of:
for(var x=5000; x > 0; x–){}
What does this mean for your benchmarks?
( )RC Roeder (evil programmer) June 18th
Yes evals are evil..but sometime needed. I never discount anything.
( )Nathan June 18th
When possible traverse the array backwards. The comparison to 0 is faster on all architectures than to a variable.
var container = document.getElementById(’container’);
( )for(var i = someArray.length – 1; i >= 0; i–) {
container.innerHtml += ‘my number: ‘ + i;
console.log(i);
}
Eric Jablow June 18th
For #6, adopting Bernard Haussner’s idea above:
(function(container, length) {
( )var result = [];
for(var i = 0, len = length; i < len; i++) {
result.push(’my number: ‘ + i);
console.log(i);
}
container.innerHtml += result.join();
})(document.getElementById(’container’), someArray.length);
Mahin Gupta June 18th
Thanks… Great tips…
( )Douglas Holt June 18th
In the Better section of #13 shouldn’t
lastName = ‘Way’,
be
lastName: ‘Way’,
( )Jack June 18th
Great! I always use ==, next time, === will be my first choice
( )daniel lopes June 18th
Don’t agree about eval and especially with Short-hand, short-hand should be used when you have only one command after the if statment.
Eval is not so bad like you said. Obviously you will not evaluate something that user type in a textfield but can be used in many situations without security issues, remember, JS is client-side so everything can be manipulated doesn’t matter if it is evaluated or not because we allways validate the things that should be maintaned in the server side.
Only care with performance when it is a problem, I will not do a for instead of each before this each starts to be slower than should be.
( )Florim Maxhuni June 19th
O thenks
( )ryan bost June 19th
Great article. I’ve been coding javascript for years and I learned some new things from the article as well as the comments.
One thing I really liked that no one mentioned however, was the Roadhouse quote in the about the author section.
( )Stefan Ashwell June 19th
Nice thanks for the tips, good tutorial!
( )Samuel June 19th
Really Good.. thanks Jeffrey!!
( )san1t1 June 19th
JSLint your code, and accept NO errors. This will force you to write it more safely, and will cover a good number of these ‘best practices’
JSMin-ify it. Remove all new lines. Anyone who thinks you don’t need curly braces will quickly get unstuck.
Have a script that does both of these and deploys your code (even if just to a different folder) before you test it.
Comments are for lengthy procedural scripts, regex and hard-to-read algorithms. Sensibly factored programs need less comments. That said, if you’re in a team, JSDocs are good, especially if you all use IDEs that support them, and your code base is BIG.
Also if you’re writing code that someone else will end up maintaining, remember it’s often worth sacrificing “clever” code for maintainable code, even if there’s a small performance loss.
Use a library (jquery and jquery ui the clear leader) to manipulate the DOM. Code that doesn’t touch the DOM, write in straight Javascript.
Don’t pollute the global namespace.
( )Anthony June 20th
If you don’t put semi-colons after functions like
var foo = function() {
};
then you should not use semicolons anywhere for consistency. It’s about time js became more python-like.
( )Nad e Ali June 20th
i think you miss one more thing that is cache your DOM object instead of calling many time
like
bad
function testFunction(){
document.getElementById(’testElement’).className=’testClass’;
document.getElementById(’testElement’).value=’test’;
document.getElementById(’testElement’).disabled=true;
}
better
function testFunction(){
var testElement=document.getElementById(’testElement’);
testElement.className=’testClass’;
testElement.value=’test’;
testElement.disabled=true;
}
btw very nice Article
( )Abhilash June 22nd
Just Great.
Just Great.
Just Great.
Thank You for this nice one.
( )Bean Taxi June 22nd
This borrows VERY heavily from Douglas Crockford’s book, blog, web site etc — I think about 20 of the 24 are Crockford’s. It’s fair to say without Douglas Crockford this list wouldn’t exist. Yet there is very little in the way of attribution. I doubt that’s malicious, but it’s not great form.
Btw I’m not a Crockford zealot. I don’t know the man, and I disagree with some of his practices (e.g. declaring all vars at the beginning of a function). But fair’s fair.
( )Bean Taxi Passenger July 14th
I agree with Bean Taxi. I just picked up the Best Parts book yesterday. In trying to find a better explanation for Doug’s preference to using array literals vs the constructor, I ran across this site; and was surprised to read how much is basically Doug’s book.
( )Ben June 22nd
Wow! Fantastic Article!!! Thanks Jeffrey!
( )Evan Larsen June 23rd
Wow, I’m so proud that I have been using most of these practices and I’ve also learned a few more, thanks!
( )Jomit June 23rd
Excellent compilation Jeffrey !! Thank you very much . . . .
( )Souvik June 24th
Thanks.
( )Greatt post
Shane Strong June 25th
Perfect post for a beginner like me thanks for the incite on good practice.
( )mahdi July 1st
In My Opinion this is the fastest way to do it .
there is no problem to put the variables inside of the forloop so you could put it out side or inside this doesn’t change the speed .
if the pushing the result in array is faster than storing them in a variable .
if (!console) { var console = {log:function(){}}; }
var container = document.getElementById(’container’);
var result = [];
for(var i = 0, len = someArray.length; i < len; i++) {
result.push(’ my number’+i);
}
container.innerHtml = result.join();
console.log(container.innerHtml);
let me know if you guys have another opinion !
( )Sambath July 22nd
best practice is very useful for me. to increase my quality in the project.
( )Thx
uma mahesh varma.seeram July 28th
very nice post and it helps alot for beginners
( )Nishit August 3rd
thats was a great article indeed.. thanks mate..
( )Ahasan habib August 4th
I want to say in a sentence that is !!!!Just amazing!!!!!
( )Garrett September 2nd
Nice tutorial. Thanks!
( )Ryan Rampersad September 18th
Good tips.
About $5, how would this affect using jQuery’s .ready and Mootools’ domready events, if scripts were loaded in the footer?
On #6, you should declare the someElements.length outside of the loop declaration because it has to fetch the same value every time it evaluates.
( )A September 21st
Douglas Crockford is the man!!! When I come be old, I want to be like him!
( )Alexsandro September 21st
Douglas Crockford is the man!!! When I come be old, I want to be like him!
P.s.: The comment above has in wrong name.
( )Anup September 21st
Great Tutorials !
It has more helpful for reducing code.
Thanks !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
( )เพชร September 22nd
very helpful for beginners
( )Eli October 6th
Another Great book is JavaScript the Missing Manual, it includes some jquery and is an overall very easy read. The Author make real life connections, and adds a little humor.
( )