Top 13 JavaScript Mistakes
Posted on October 13, 2010Prem Gurbani Frontend Architect
Sergio Cinos Architecture Engineer
Recently we’ve defined a list of most common Javascript mistakes that developers make. These cover a wide variety of topics and I’m sure you will find among them at least one that you’ve committed yourself. We describe the theory behind each of the problems/bad practices and show concrete solution(s).
Do you think we’re missing something obvious? Leave a comment and let us know about it.
1. Usage of for..in to iterate Arrays
Example:
var myArray = [ “a”, “b”, “c” ];
var totalElements = myArray.length;
for (var i = 0; i < totalElements; i++) {
console.log(myArray[i]);
}
The main problem here is that the for..in statement does not guarantee the order. Effectively this means that you could obtain different results at different executions. Moreover, if someone augmented Array.prototype with some other custom functions, your loop will iterate over those functions as well as the original array items.
Solution: always use regular for loops to iterate arrays.
var myArray = [ “a”, “b”, “c” ];
for (var i=0; i<myArray.length; i++) {
console.log(myArray[i]);
}
2. Array dimensions
Example:
var myArray = new Array(10);
There are two different problems here. First, the developer is trying to create an array already containing 10 items, and it will create an array with 10 empty slots. However, if you try to get an array item, you will get ‘undefined’ as result. In other words, the effect is the same as if you did not reserved that memory space. There is no really good reason to predefine the array length.
The second problem is that the developer is creating an array using Array constructor. This is technically correct. However it’s slower than the literal notation.
Solution: Use literal notation to initialize arrays. Do not predefine array length.
var myArray = [];
3. Undefined properties
Example:
var myObject = {
someProperty: “value”,
someOtherProperty: undefined
}
Undefined properties (such as someOtherProperty in the above example)
will create an element in the object with key ’someOtherProperty’ and
value ‘undefined’. If you loop through your array checking the
existence of an element the following 2 statements will both return
‘undefined’:
typeof myObject['someOtherProperty'] // undefined
typeof myObject['unknownProperty'] // undefined
Solution: if you want to explicitly declare a uninitialized properties
inside an object, mark them as null
var myObject = {
someProperty: “value”,
someOtherProperty: null
}
4. Misuse of Closures
Example:
function(a, b, c) {
var d = 10;
var element = document.getElementById(‘myID’);
element.onclick = (function(a, b, c, d) {
return function() {
alert (a + b + c + d);
}
})(a, b, c, d);
}
Here the developer is using two functions to pass the arguments a, b and c to the onclick handler. The double function is not needed only adding complexity to the code.
The variables a, b and c are already defined in the inner function because they are already declared as parameters in the main function. Any function inside the inner function will create a closure with all variables defined by main function. This includes ‘regular’ variables (like d) and arguments (like a, b and c). Thus It is not necessary to pass them again as parameters using a auto-executable function.
See JavaScript Closures FAQ for an awesome explanation about closures and contexts.
Solution: use closures to simplify your code
function (a, b, c) {
var d = 10;
var element = document.getElementById(‘myID’);
element.onclick = function() {
//a, b, and c come from the outer function arguments.
//d come from the outer function variable declarations.
//and all of them are in my closure
alert (a + b + c + d);
};
}
5. Closures in loops
Example:
var elements = document.getElementByTagName(‘div’);
for (var i = 0; i<elements.length; i++) {
elements[i].onclick = function() {
alert(“Div number “ + i);
}
}
In this example, we want to trigger an action (display “Div number 1”, “Div number 2”… etc) when the user clicks on the different divs on the page. However, if we have 10 divs in the page, all of them will display “Div number 10”.
The problem is that we are creating a closure with the inner function, so the code inside the function has access to variable i. The point is that i inside the function and i outside the function refers to the same variable (i.e.: the same position in memory). When our loop ends, i points to the value 10. So the value of i inside the inner function will be 10.
See JavaScript Closures FAQ for an awesome explanation about closures and contexts.
Solution: use a second function to pass the correct value.
var elements = document.getElementsByTagName(‘div’);
for (var i = 0; i<elements.length; i++) {
elements[i].onclick = (function(idx) { //Outer function
return function() { //Inner function
alert(“Div number “ + idx);
}
})(i);
}
The outer function is a function that executes inmediatly, receiving i as a parameter. That parameter is called idx inside the outer function, thus inner function creates a closure with idx (instead of i). Therefore idx is completly different from across iterations (i.e. they point to different memory address). This example is very important to understand how closures work. Be sure to read it and play with the code in your browser until you fully understand what’s going on there.
6. Memory leaks with DOM objects
Example:
function attachEvents() {
var element = document.getElementById(‘myID’);
element.onclick = function() {
alert(“Element clicked”);
}
};
attachEvents();
This code creates a reference loop. The variable element contains a reference to the function (it is assigned to onclick properties). Also, function is keeping a reference to the DOM element (note that inside the function you have access to element because of the closure). So JavaScript garbage collector cannot clean neither element nor the function, because both are referenced by each other. Most JavaScript engines aren’t clever enough to clean circular references.
Solution: avoid those closures or undo the circular reference inside the function
function attachEvents() {
var element = document.getElementById(‘myID’);
element.onclick = function() {
//Remove element, so function can be collected by GC
delete element;
alert(“Element clicked”);
}
};
attachEvents();
7. Differentiate float numbers from integer numbers
Example:
var myNumber = 3.5; var myResult = 3.5 + 1.0; //We use .0 to keep the result as float
In JavaScript, there is no difference between float and integers. Actually, every number in JavaScript is represented using double-precision 64-bits format IEEE 754. In plain words, all numbers are floats.
Solution: don’t use decimals to “convert” numbers to floats.
var myNumber = 3.5; var myResult = 3.5 + 1; //Result is 4.5, as expected
8. Usage of with() as a shortcut
Example:
team.attackers.myWarrior = { attack: 1, speed: 3, magic: 5};
with (team.attackers.myWarrior){
console.log ( “Your warrior power is ” + (attack * speed));
}
Before talking about with(), let’s see how JavaScript contexts works. Each function has an execution context that, put in simple words, holds all the variables that the function can access. Thus the context contain arguments and defined variables. Also a context points to a “parent” context (the context that our caller function has). For example, if functionA() calls functionB(), functionB’s context points to functionA’s context as its parent context. When accessing any variable inside a function, the engine first search in his own context. If not found, it switches to the parent context and so on until it finds the variable or it reaches the end of the context chain. Execution contexts are what makes closures work.
What with() actually does, is to insert an object into our context chain. It injects between my current context and my parent’s context. In this way, the engine first searches in the current context for the requested variable, and then it searches for it in the recently injected object, and finally in the “real” parent context. As you can see, the shortcut used in the example code above is a side effect of using context injection. However usage of with() is very slow, and thus using it for shortcuts is just insane.
Just a side note. Every book recommends not to use with(). Nevertheless all of them are focused on its usage as a shortcut. Context injection is really useful and you may find that you need to use it in advanced JavaScript. In those cases, it’s acceptable to use with() with its real meaning. Although be aware that it’s it’s still very slow from a performance perspective.
See JavaScript Closures FAQ for an awesome explanation about closures and contexts.
Solution: don’t use with() for shortcuts. Only for context injection when you really need it.
team.attackers.myWarrior = { attack: 1, speed: 3, magic: 5};
var sc = team.attackers.myWarrior;
console.log(“Your warrior power is ” + (sc.attack * sc.speed));
9. Usage of strings with setTimeout/setInterval
Example:
function log1() { console.log(document.location); }
function log2(arg) { console.log(arg); }
var myValue = “test”;
setTimeout(“log1()”, 100);
setTimeout(“log2(” + myValue + “)”, 200);
Both setTimeout() and setInterval() can accept either a function or a string as the first parameter. If you pass a string, the engine will create a new function using Function constructor. This is very slow in some browsers. Instead pass the function itself as the first argument; it’s faster, more powerful and clearer.
Solution: never use strings for setTimeout()or setInterval()
function log1() { console.log(document.location); }
function log2(arg) { console.log(arg); }
var myValue = “test”;
setTimeout(log1, 100); //Reference to a function
setTimeout(function(){ //Get arg value using closures
log2(arg);
}, 200);
10. Usage of setInterval() for heavy functions
Example:
function domOperations() {
//Heavy DOM operations, takes about 300ms
}
setInterval(domOperations, 200);
We can have a problem when using intervals where operation time is bigger than the interval step time. In the example we are doing a complex (i.e.: long) operation with DOM objects every 200ms. If the domOperations() function takes more than 200ms to complete, each step will overlap with the previous step and eventually some steps may get discarded. This can become a problem.
setInterval() schedules a function to be executed only if there isn’t another execution already waiting in the main execution queue. The JavaScript engine only adds the next execution to the queue if there is no another execution already in the queue. This may yield to skip executions or run two different executions without waiting 200ms between them. To make it clear, setInterval() doesn’t take in account how long it takes domOperations() to complete its job.
Solution: avoid setInterval(), use setTimeout()
function domOperations() {
//Heavy DOM operations, takes about 300ms
//After all the job is done, set another timeout for 200 ms
setTimeout(domOperations, 200);
}
setTimeout(domOperations, 200);
11. Misuse of ‘this’
There is no example for this common mistake as it is very difficult to build one to illustrate it. The value of this in JavaScript is very different from other languages, where the this behaviour is usually clearer. However, in JavaScript this is a bit different.
First of all, the value of this inside a function is defined when the function is called, not when it is declared. Its very important to understand this, because the value of this depends on how the function is called. In the following cases, this has a different meaning inside myFunction
* Regular function: myFunction(‘arg1’);
this points to the global object, wich is window for all browers.
* Method: someObject.myFunction(‘arg1’);
this points to object before the dot, someObject in this case.
* Constructor: var something = new myFunction(‘arg1’);
this points to an empty Object.
* Using call()/apply(): myFunction.call(someObject, ‘arg1’);
this points to the object passed as first argument.
In this way you can have the same function (myFunction in the example above), that internally use this. However, the value of this is not related to the function declaration itself, only to the way that function is called.
12. Usage of eval() to access dynamic properties
Example:
var myObject = { p1: 1, p2: 2, p3: 3};
var i = 2;
var myResult = eval(‘myObject.p’+i);
The main problem lies in that starting a new execution context with eval() is extremely slow. The same can be achieved using square bracket notation instead of dot notation.
Solution: use square bracket notation instead of eval()
var myObject = { p1: 1, p2: 2, p3: 3};
var i = 2;
var myResult = myObject[“p”+i];
13. Usage of undefined as a variable
Example:
if ( myVar === undefined ) {
//Do something
}
This check usually works, but it does by pure chance. In the code above undefined is effectively a variable. All JavaScript engines will create the variable window.undefined initialized to undefined as its value.
However note that variables isn’t read-only, and any other code can change its value. It’s very weird to find a scenario where window.undefined has a value different from undefined. (nobody will never actually do undefined = 10;). But why take the risk? It is better to use typeof checks.
Solution: use typeof when checking for undefined.
if ( typeof myVar === “undefined” ) {
//Do something
}






October 13, 2010 at 12:06 pm
Awesome article… please, keep posting more things like these.
October 28, 2010 at 5:28 pm
try to make some code to change text like write bigger or in other color than black
November 21, 2010 at 9:55 pm
Interesting article, though it might be worth increasing the heading size so that you can identify the 13 mistakes by skimming the document.
December 1, 2010 at 7:41 am
Thanks for the article, you not only pointed out the problems but also did a great work on explaining where each problem lies and how to fix it.
Maybe I’m missing something, but I’d say that there are a couple of incomplete examples:
- in problem #1 the examples are pretty similar (the only difference is that the 1st one is storing the array length in a variable, I ignore if it gives some performance gain) and none of them is iterating with “for…in” as the text describes.
- problem #6 mentions that the function defined for the onclick event is referencing the clicked element as a closure, but there is only an alert inside the function. Does it actually keep a reference to the element even if it doesn’t reference it as a closure? If not, maybe the example could reference the element inside the alert sentence to say something about it.
As I said, maybe I’m missing something as I’m not an expert javascripter, thanks again!
December 30, 2010 at 12:48 pm
Estimado señor,
El método que utilizan para describir como los usuarios deben insertar en sus web el botón compartir, me parece bastante complicado, principalmente porque no tengo idea de como codificar en JavaScript “encodeURIComponent()” mi URL: http://www.mundoweekend.com/entradas-nochevieja-fin-de-ano.htm y tampoco explica como hacerlo.
Creo que sería una buena idea que lo automatizaran un poco más como hace Facebook, en el cual, no hace falta ni descargarse la imagen png en tu propio servidor.
Es solo una sugerencia, pero que me gustaría aprovechar para preguntarle, ¿cómo puedo codificar esa url que le he indicado?
Gracias.
January 5, 2011 at 11:01 pm
mola
January 25, 2011 at 9:41 am
Error in 9 (myValue instead of arg in the setTimeout() solution):
setTimeout(function(){ //Get arg value using closures
log2(myValue); // << myValue instead of arg
}, 200);
March 24, 2011 at 1:27 pm
If you want to know more about these language’s quirks there is a new site called JavaScript Garden that explains very well a lot of things (including several of this list).
http://bonsaiden.github.com/JavaScript-Garden/
April 13, 2011 at 12:40 pm
For #13 you could also use the following:
(function(undefined) {
if ( foo === undefined) {
// Do stuff
}
})();
right?
April 14, 2011 at 6:45 am
There are so many problems with this article that I don’t know where to begin. Please, stop writing about Javascript until you have more experience.
April 14, 2011 at 7:34 am
good fork but to iterate a for, better with:
for(i in myArray)
console.log(myArray[i]);
April 14, 2011 at 7:51 am
I love this recomendations. They’re so util, but some of these are mistakes in other scripting languages too, for instance array behavior is a little similar on Python. But some of these practices comes from traditional languages like Java, C, C++, etc.
I think that a person that starts and learn programming with javascript… not usually make this mistakes.
April 14, 2011 at 8:34 am
Esta muy bueno el post
tengo una duda sobre el primer punto.. no veo ningún “for..in” son los 2 for normales.
Y además el primer for esta bien hecho y el segundo que dice que esta bien, esta “mal”.
var myArray = [ “a”, “b”, “c” ];
for (var i=0; i<myArray.length; i++) {
console.log(myArray[i]);
}
¿por qué?
Porque en cada iteración esta pidiendo la cantidad de elementos en el array, esto es más lento que si guardas el largo del array en una variable como lo hicieron en el primer for
var myArray = [ “a”, “b”, “c” ];
var totalElements = myArray.length;
for (var i = 0; i < totalElements; i++) {
console.log(myArray[i]);
}
April 14, 2011 at 9:22 am
You’re first code example should be:
for (var el in myArray){}
And the right way to doing it:
for(var i = 0, iMax = myArray.length; i < iMax; i++){}
April 15, 2011 at 3:33 am
I am interested to see people calling themselves “Front end architects”, I was waiting for this to happen.
Very soon we will have Rear End architects, Side Archictects, Top Architects, Bottom Architects and Architectural Architects.
Anyway, I like the background color of your web page, you should be commended for that work.
April 15, 2011 at 5:26 am
I stopped reading after the first 2 points. Clearly the author has no idea about JavaScript, and looks like he didn’t bother to research as well.
Poorly written article with incorrect information.
April 15, 2011 at 6:06 am
Nice article.
1) Your first example doesn’t have a for in.
Basically you wrote the same operations twice.
The first example should be….
var myArray = [ 'a', 'b', 'c' ];
for (var prop in myArray ) {
console.log(myArray[ prop ]);
}
2) new Array() is actually very useful. It does the following two statements.
var arr = new Array( desiredLength );
// Same as below
var arr = [];
arr.length = desiredLength;
Here’s an article that I wrote about leading and trailing zeros in floats in javascript.
http://bateru.com/news/2011/04/code-of-the-day-javascript-significant-figures/
April 15, 2011 at 7:22 am
Your length usage is very wrong:
var myArray = [ “a”, “b”, “c” ];
for (var i=0; i<myArray.length; i++) {
since length has to be calculated every time
should be:
var myArray = [ “a”, “b”, “c” ];
for (var i=0, j=myArray.length; i<j; i++) {
April 15, 2011 at 12:48 pm
FYI, setting the length property of an Array instance (“mistake” #2) may help to improve greatly perfs.
See http://jsperf.com/array-push/8
April 15, 2011 at 2:45 pm
Excellent article! Congrats.
April 15, 2011 at 2:50 pm
Your for…in example for arrays doesn’t actually show the for…in use. Both the good and bad examples are using a standard for loop.
April 15, 2011 at 3:03 pm
Item #6 is not quite correct.
First of all, you should not use .onclick = function() {} syntax to attach events. Use the w3c model (and the IE model for IE).
Secondly, you can’t use “delete” to unreference a local variable declared using var. (Besides, even if that worked, your event handler does not remove the reference until it has executed at least once, so there could still be a leak). The correct way would just be to set “element” to null after you have done with it in attachEvents function.
April 15, 2011 at 8:40 pm
For #2. There are some uses of new Array(number). For example if you need to generate a string of 10 dots (.) just write: (new Array(11)).join(‘.’). Haven’t tested if it is faster or slower, then to write a for / while loop, but it is clean enough for this task.
To check if a key is in the object use the in operator opposed to `typeof`. This is for #3 and #13
April 15, 2011 at 11:06 pm
Awesome article, more like this please!
Code syntax coloring would help though. Check out http://jsfiddle.net/ you can set up these examples there and embed them in your page. It’s rather brilliant.
Also, I second what Larry said above.
April 16, 2011 at 11:27 pm
In #1, it looks like you meant to edit the second code snippet with the length optimization, but you accidentally overwrote the first code snippet.
Right now, the first snippet does not have a for…in iteration. It’s the same as the second snippet but with myArray.length pulled out of the loop.
April 25, 2011 at 4:21 pm
As other people have pointed out, there isn’t a “for…in” example in #1. Beyond that, there are a few things #1 didn’t mention:
You are correct in stating “for…in” doesn’t guarantee order, which is why you should (almost) always use a standard for loop and increment the count up. But consider this example:
var myArray = ["a", "b", "c"];
myArray[10] = “j”;
Now check myArray.length and see what happens. It’s 11, even though there are only 4 items. Array.length is one more than the highest index, NOT the count of items in an array.
That means in the standard “for” loop would return undefined for items 3 through 9. A for-in doesn’t have this issue.
You may want to consider myArray.forEach(callback) as an alternative.
April 26, 2011 at 4:35 pm
For #13, you can just do
if (myVar === void 0) {
// Do something
}
The void operator is guaranteed to return undefined regardless of its operand. This is shorter than both typeof and checking against window.undefined.
June 9, 2011 at 9:54 am
As other people have pointed out, there are different mistakes and inaccuracies in your top JS mistakes list. But great post anyway and specially good tips for closure.
October 7, 2011 at 10:44 am
I prefer this type of closure in loops (#5). Shorter to write :
var elements = document.getElementsByTagName(‘div’);
for (var i = 0; i<elements.length; i++) {
(function(idx) { //Outer function
elements[i].onclick = function() { //Inner function
alert("Div number " + idx);
};
})(i);
}
October 7, 2011 at 3:33 pm
For #8
The with statement adds a computed object to the front of the scope chain of the current execution
context, then executes a statement with this augmented scope chain, then restores the scope chain.
So when the engine searches the requested variable ,it first searches the injected obj, and then it searches for it in Activation Obj of current context, and finally in the “real” parent context.