Tips for Creating Reliable Javascript

Published:
Updated:
This article is aimed at those who are newcomers to Javascript.   Most if not all of this information can be found on the web, however, it's not all in one place, and it may not be under a "best practice" heading or written in a way that those new to Javascript may understand, so I have decided to create this article to consolidate some of those findings.

Many of us who begin programming in Javascript start by using code copied from the web.  The issue with this is a lot of Javascript code is, unfortunately, poorly written, or no longer current.  This can lead to a lot of bad practices for a lot of new Javascript programmers.  Hopefully this article will point out a few of the biggest "no-no"'s and show you how to do it the correct way.

Eval is Evil
Those are Douglas Crockford's words, not mine.  However, that doesn't make them any less true.  There are two reasons eval is evil: Performance and Security.
Every time eval is called, the javascript interpreter must be started and evaluate the code.  This is an intensive process, although you may not notice it.  If the eval was in a loop, or was called a number of times, the overhead would definitely be noticeable.
Since eval will evaluate code that is passed to it, it is a potential security risk, especially if you are eval'ing code that contains user input.

The most common misuse of eval I regularly see is the following:
eval('document.' + someElementInAVariable + '.someproperty = whatever');

Open in new window

If you need to access a property or object, in which the name of that property or object is stored in a variable, you can use the bracket([]) notation.
document[somElementInAVariable].someproperty = whatever;

Open in new window


Eval truly is evil.  That isn't to say that it isn't sometimes a necessary evil.  There are some cases where it's use is allowed, or even mandated(such as JSON).  Those cases are on a very short list, so odds are if you are using eval, you are doing it wrong.

Type Coercion...conversion...whatever.
Javascript's is a weakly typed language, and in many cases, will implicitly coerce(convert) the type for you.  For instance, when adding a number(123) with a string('Boston') you will get: 123Boston.  This is great when you are adding a number and string and wanting a string in return, but what if you were trying to get a number?
var x = '1';
                      var y = 1;
                      alert(x + y);  //expecting 2?  think again!  you'll get 11.

Open in new window

Even worse, what if you were testing for a boolean true/false value?
var foo = false;
                      if(foo == 0) 
                          alert('Foo is false!');
                      }

Open in new window

Here, 1 and 0 will evaluate to true/false respectively.  Is this really what you wanted?  Maybe yes; maybe no.

In our first example, we want to convert the type to  a number:
var xNumber = parseInt(x, 10);

Open in new window

In our second example, we can use the '===' comparison operator, which does not do type coercion:
var foo = false;
                      if(foo === 0) 
                          alert('Foo is false!');
                      }

Open in new window


When you are mixing types in Javascript, it is safer to explicitly convert the type yourself, or to make comparisons that also check the type of the variable.

Braces({}) are awkward, in life and Javascript
I admit it.  I'm guilty of this next infraction.  I used to write all my javascript code this way:
function foo()
                      {
                      // code goes here
                      }

Open in new window

However, I noticed that sometimes my code was not working as intended, and some of my functions were not returning the results I expected:
function SeaCritter()
                      {
                          return
                          {
                              firstName: 'Spongebob',
                              lastName: 'SquarePants'
                          };
                      }
                      var sc = SeaCritter();
                      alert('Hello, my name is ' + sc.firstName + ' ' + sc.lastName);

Open in new window

This code will throw an error in most(if not all) browsers.  The reason for this is how the interpreter handles some statements(like return) and the brace that is placed behind them.

If we change the code, it works as expected:
function SeaCritter() {
                          return {
                              firstName: 'Spongebob',
                              lastName: 'SquarePants'
                          };
                      }
                      var sc = SeaCritter();
                      alert('Hello, my name is ' + sc.firstName + ' ' + sc.lastName);

Open in new window


The moral of the story is to use the opening "{" on the same line as the opening statement.

Variables sometimes need some Closure.
Closures are another powerful feature of Javascript, but they can be a real headache when used in a loop.
function registerOnClick() {
                          for(var x = 0; x < 5; ++x) {
                              document.getElementById(x).onclick = function() {
                                  alert(x);
                              }
                          }
                      }
                      window.onload = registerOnClick;

Open in new window

You might expect that your elements with ID 0-4 would each alert 0 - 4 depending on which button was pressed.  However, you'd be wrong.  All of the buttons will alert 5!  What happened?  The issue here is the way closures work.  When you use a variable in a closure that is declared in another scope, the closure forms a link with that variable, and will hold on to that value even after the variable has gone out of scope.  Since javascript uses function scope variables, at the end of the function, x was equal to 5, so the closure remembers that.
Some new implementations of Javascript introduced the 'let' keyword, which allows you to declare a new scope for a variable.  However, it is currently not widely implemented.

Thankfully, there is a way to get the results we want without too much trouble:
function registerOnClick() {
                          for(var x = 0; x < 5; ++x) {
                              document.getElementById(x).onclick = function(v) {
                                  return function() {
                                      alert(v);
                                  }
                              }(x);
                          }
                      }
                      window.onload = registerOnClick;

Open in new window

This creates an anonymous function and passes our variable to it.  This anonymous function is immediately executed and returns the function that we want to run on our onclick event.  This creates a new scope for our variable, preserving the value we want to pass to our onclick event.

Timeout! Let's Talk About setTimeout
setTimeout and setInterval are two methods use to delay the execution of code, or to run code at certain intervals.  There are three ways to pass a function to these:
setTimeout("doThis()", 1000);
                      setTimeout(doThis, 1000);
                      setTimeout(function() {
                        doThis();
                      }, 1000);

Open in new window


The second and third way are perfectly fine.  The first one, however, has a problem.  When you pass a string to setTimeout or setInterval, an eval must be preformed(see Eval is Evil).

If you need to run a function with no argument, use the second method.

If you need to run a function with arguments, use the third method.
setTimeout(function() {
                        doThis('stuff', 'i', 'am', 'passing');
                      }, 1000);

Open in new window


What do you think about comments?  No comment!
<!-- and --> were once used in Javascript to prevent browsers that did not understand Javascript from having a catastrophic meltdown when it was encountered.  Unless you are programming Javascript for a specific browser that doesn't understand Javascript code(Did you see what I did there?), you don't need to include them in your code.

Sorry, I don't speak Javascript
The most common way to create a <script> tag is as follows(This is also the WRONG way!):
<script language="Javascript">...</script>

Open in new window


The "language" attribute was deprecated several years ago.  The correct way to add a script tag is by using the "type" attribute:
<script type="text/javascript">...</script>

Open in new window


Infinite loops.  Infinite loops.   Infinite loops.  Infinite loops.  Ok, I think you get the idea!
When using a for loop, it's very common to see it written this way:
for(var i = 0; i < someObject.length; i++) {
                        // doing all sorts of stuff
                      }

Open in new window


In most cases, this is ok, but what happens if the length of the object changes in the middle of the loop?
for(var i = 0; i < someObject.length; i++) {
                         //doing all sorts of stuff here and for some known or unknown reason, the length property of our object has changed
                      }

Open in new window


This could result in a few things:
1)  The loop terminates too early
2)  The loop terminates later than expected
3)  The loop doesn't terminate at all!

Just to be on the safe side, you probably want to set the .length property of the object to a variable.  This way, the variable can remain constant(unless you explicitly change it), while the .length property can be modified safely.
for(var i = 0, e = someObject.length; i < e; i++) {
                         //doing all sorts of stuff here and if our length property changes, the number of times our loop will run should not.
                      }

Open in new window



Hopefully, you now have a good understanding of how to handle some of the more common pitfalls when using Javascript.  Be prepared to run across more as you begin diving deeper into the language.  Javascript can be an elegant language, but it can also be a real pain to work with unless you know how to use it effectively.

Good luck and happy coding!
5
3,414 Views

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.