Top 10 Things that JavaScript Got Wrong
Tutorial Details
- Topic: JavaScript
- Difficulty: Intermediate
JavaScript, if only by default, is one of the most popular programming languages available. Over the years, it’s been labeled as a nightmare to work with, and, to some extent, this is true! However, more often than not, what people mean to say is that the DOM API is a nightmare. Nevertheless, there are a handful of flat-out errors in the language.
I’d like to make a note that I love JavaScript. This article is only meant for some fun, and for us to be aware of some its short-comings.
1. The Name. JavaScript is NOT Java
We’ll start with a fun jab at the name choice. While it was originally called Mocha, and then LiveScript, it was later changed to JavaScript. According to history, its similarities to the name Java was the result of a collaboration between Netscape and Sun, in exchange for Netscape bundling the Java runtime within their popular browser. It’s also been noted that the name came, almost as a joke, due to the rivalry between LiveScript and Java for client-side scripting.
Nevertheless, it resulted in thousands of “JavaScript has nothing to do with Java” comments in forums across the web!
2. Null is an Object?
Consider this…
console.log(typeof null); // object
This makes zero sense. If null is the absence of a value, then how could its type be “object?” The simple answer is that it’s flat-out an error that dates back to the first release of JavaScript – one that was even incorrectly carried over to Microsoft’s JScript.
3. NaN !== NaN
NaN, as we’d expect refers to a value that is not a legal number. The problem is that NaN isn’t equal to anything…including itself.
console.log(NaN === NaN); // false
This should be wrong. Instead, if you want to determine if a value is indeed NaN, you can use the isNaN() function.
Update: after reading through some of the brilliant comments, particularly the ones relating to NaN being similar to infinity, it then makes perfect sense that NaN would not equal itself. But it can still be confusing. Refer to the comments for an in depth discussion on this!
4. Global Variables
The dependence upon global variables is widely considered to be far and away the worst part of JavaScript. For simple projects, much like the quick tips on this site, it doesn’t truly make a difference. However, the real burden of globals come into play when you begin referencing multiple scripts, without any knowledge of how they’re created, or named. If they happen to share the same name as one of your variables, your program is going to throw some sort of error.
“The problem with JavaScript isn’t just that it allows them (global variables), it requires them.” – Crockford
5. User-Agent Strings Report Mozilla. Ever Wonder Why?
Alright – this one isn’t the fault of JavaScript. I cheated a bit. It’s because of the browser vendors. Having said that, user-agent string detection is very common in JavaScript; so it’s important to know what you’re dealing with. It probably doesn’t belong in this list, but who cares! It’s good to know.
This one isn’t as much a mistake as it was an unavoidable decision. For example, open Safari, access the Web Inspector, and log the user agent string into the console.
console.log(navigator.userAgent); // Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10
Note that first string of characters: Mozilla/5.0. Why would Safari identify it as a Mozilla based browser? Though it later correctly identifies itself, that still doesn’t explain why they’d bother to mislead programmers. In fact, you’ll find that most browsers identify themselves as Mozilla. The answer goes back a decade, and is, again, less an error, and more an unavoidable circumstance.
For those unfamiliar, a user-agent string is simply meant to identify the browser and its version. As an example, the first ever browser, Mosaic, had a user-agent string that looked like so:
Mosaic/0.9 // browser name / version number
This makes perfect sense. And when Netscape came onto the scene, they kept Mosaic’s usage, and also added an encryption type section.
Mozilla/2.02 [en] (Win95; I) // browser name / version / encryption
So far so good. The problems came into play when – wait for it – Internet Explorer 3 was released. Keep in mind that, when they launched, Netscape was the most popular browser available. In fact, many servers and programs were already implementing user-agent detection in order to identify Netscape. Though this is a highly debated topic today, back then, it wasn’t much of an issue. If IE had used their own user-agent string, it would have looked something like this:
MSIE/3.0 (Win95; U)
This would have left them at a huge disadvantage, because Netscape was already being identified by many servers. As such, the developers decided to incorrectly identify the browser as Mozilla, and then append an additional set of information labeling it as Internet Explorer.
Mozilla/2.0 (compatible; MSIE 3.0; Windows 95)
Nowadays, user-agent detection is a last effort, and its considered so precisely for this reason. You’ll find that most browsers followed IE’s lead in identifying themselves as Mozilla. Think of it as a chain reaction.
Further Reading
I highly recommend that you read Nicholas Zakas’s “History of the User-Agent String,” if you’d like to delve deeper.
6. Scope Inconsistencies
Consider the following code:
// Create a function that will call a function with the name equal to parameter fn.
function foo(fn) {
if (typeof fn === "function") {
fn();
}
}
// Create an object with a property and a method.
var bar = {
barbar : "Hello, World!",
method : function() {
alert(this.barbar);
}
};
bar.method(); // Alerts Hello, World!
foo(bar.method); // If we call the foo function add pass the "bar.method" method, it somehow alerts "undefined."
foo(function() { bar.method(); }); // alerts Hello, World, after
The reason why foo(bar.method) does not render the same result is because the method function will be called as a method of the window object, rather than bar. To fix this, we must call bar.method() from within the passed anonymous function.
Thanks so much to Jeremy McPeak for notifying me of this error.
7. The Use of Bitwise Operators
JavaScript shares many similarities with Java – one of them being the set of bitwise operators.
- & – and
- | – or
- ^ – xor
- ~ – not
- >> – signed right shift
- ??? – unsigned right shift
- << – left shift
Consider the first item, &; it would be much more efficient to use the && operator, as it’s quicker. This is because JavaScript isn’t the same as Java, and doesn’t have integers. As such, a relatively length process is required to convert the operand, do something with it, and then convert it back.
This is why you can get away with using & for “and”, and | for “or” – even though you should be using && and ||.
8. Too Many Falsy/Bottom Values
Maybe this isn’t specifically an error in JavaScript, but it certainly makes the learning process, especially for beginners, a tough one. Values like null, false, and undefined almost mean the same thing, but there are differences that can be confusing to understand.
Falsy Values
To test, open up the console in Firefox, and find the boolean of the following items.
!!(0); // false
!!(false); // false
!!(''); // false
!!(null); // false
!!(undefined); // false
!!(NaN); // false
Please note that any other values will be interpreted as truthy.
More than an error, this many falsy values is just confusing!
9. It Can’t Do Arithmetic
Okay, okay – I’m 99% teasing with the heading above. But JavaScript does have a few minor issues when working with decimals, for example, things like money transactions. For example, open up your console, and log “.2 + .4″. We would expect it to display “.6″, correct? Well it does, and it doesn’t!
console.log(.2 + .4); // 0.6000000000000001
How come? At a high level, it’s because JavaScript used the IEEE Standard for Binary Floating-Point Arithmetic. I, probably like you, don’t fully understand exactly what that specifies, but just know that, when dealing with decimal fractions, results can vary slightly from what you might expect. Keep in mind that integer arithmetic is perfect, so this really isn’t a huge issue.
10. Code Styling Isn’t your Choice!
When it comes to your coding style, it’s exactly that: your style. Some people prefer to place their curly braces on the same line as the control, others prefer that it goes on its own.
// braces on the right
return {
foo : bar
};
// braces on their own line
return
{
foo : bar
};
Dependent upon the first web dev book we read, or how our teacher taught us, it’s perfectly acceptable to use either of the methods above, or even a combination of the two. The problem with JavaScript is that it’s not your choice!
I learned this particular example from a lecture that Doug Crockford gave around a year ago. Consider the return statement from above. Believe it or not, they ARE NOT equal. Don’t believe me? Try this out. Add the following to some HTML page.
var foo = function() {
return {
a : 'b'
};
}();
alert(foo.a); // b
The code above simply creates a variable called foo, which is equal to the returned object. When we alert(foo.a), we, as expected, see an alert box with a value of ‘b.’ Now, simply take that opening curly brace, from the return statement, and push it down to its own line, like so.
return
{
a : 'b'
};
If you run it in your browser again, you’ll receive a Firebug error, logging that “foo is undefined.” What the hell!? :)
So why does JavaScript do this? It’s because of something called “semicolon insertion.” Essentially, JavaScript will attempt to correct our bad coding. If, for instance, it thinks that you’ve left off a closing semicolon, it’ll go ahead and add it on for you. Though this was originally intended to be a convenience, especially for newer JavaScripters, it’s actually a very bad thing when you don’t have control over your own code, as demonstrated above.
In our example, there’s no way to determine why foo.a returns “undefined. ” Now that we’re aware of semicolon insertion, the reason it’s undefined is because JavaScript will add a semicolon to the end of the return statement.
return; // JS incorrectly adds this semicolon.
{
a : 'b'; // It'll add a semicolon here as well, because it doesn't realize that this is an object.
};
So, if we immediately return, it has no idea what the property “a” is, thus, resulting in “undefined.”
Conclusion
As I mentioned at the beginning of this article, I love JavaScript and use it daily. But that doesn’t mean that there aren’t some really awful errors in the language. I’d love to hear your thoughts in the comments! Thanks for reading. Retweets and Diggs are always appreciated! Thanks so much to Jeremy McPeak, Doug Crockford, Nicholas Zakas, and John Resig: I referred to your tutorials and books when preparing this article.
- Follow us on Twitter, or subscribe to the Nettuts+ RSS Feed for the best web development tutorials on the web.

My fav is number 3, that got a little chuckle out of me.
#9.
That is a rounding error, and the nature of computer hardware.
If you’ve ever used CSS to create columns, more likely than not you’ve probably learned not to set every column to an exact percentage value, instead you would leave the last column undefined so that the browser can fill the rest of the width in by itself – or you can set each column to a slightly less value than in reality.
The problem is if you tell the browser explictly a small rounding error can push the column down to the next line.
With too little script you can accomplish the unelectable. Thanks for sharing these 10 facts about javascript
#5 is not quite true anymore. Opera does not identify itself as Mozilla/5.0 anymore. It proudly says “Opera/9.80 (…)” upfront. So in fact, User-Agent sniffing woes are not actually relevant anymore.
No one language scape of its scenery, all have flaws, it will not change on JS or ECMAScript!
Null as an object is actually very useful. It allows you to differentiate between a variable that has not been defined, and a variable that has been defined but which has a null value.
Analogously, in Ruby, there is a defined? method, but the nil value has type NilClass, which overrides Object#nil? to return true.
Really excellent article. JavaScript indeed has it’s quirks. However, I would recommend to remove the section about arithmetics. It shows a bit of lack of understanding how number systems work.
Whereby it is easy to write 1/3 or π on paper, it is not possible to represent any infinitely long number in finite binary form. There are many standards for binary arithmetics on decimal numbers but all off them have there shortcomings.
In almost many programming languages the following loop never terminates:
f = 0;
while (f != 10) f = f + 0.1; // 10 is represented as 10.000…0005
Of course it is possible to represent a decimal number to any finite precision, but that requires flexible-size data structures and more overhead on the operations. It is a rule in any language to not to do financial calculation with float or double types. Instead one uses special objects, like BigDecimal in Java which support arbitrary precision or can throw an exception if precision would be lost.
Very uninformative.
10: a special case. You HAVE to understand semicolon insertion, you can still code any way you like understanding the consequences. Every language has restrictions on whitespace.
9: most interpreted languages suffer the same problem, including ruby.
7: never seen anyone using bitwise operators instead of && or ||. You can do this same kind of stupidity in any language you like.
6: that’s not inconsistency, it’s the way scoping works. You have to understand the logic behind ‘this’ to write proper code. One can see you lack some basics on line 1, ” call a function with name equal to parameter fn”. The parameter is the function object itself, not a string/name.
5: hardly an issue when you shouldn’t use it to start with.
4: at most one global is ever required, you can do everything inside a different scope. PHP suffers much more from this than JS will ever do.
A month long poll at i-programmer came up with the results:
that 35% thought it was a great language – as long as you understood it – versus 28% who thought it “terrible”.
but went on to point out
Another 16% thought that it was the “Web language of the future”. So that means that 51% thought positive things about JavaScript compared to only 28% with strong negative emotions
There is also an interesting article discussing why JavaScript is a gem.
I can’t get over the 16% who think that JavaScript is the web language of the future,,,,,
nice blog…
I am also a web programmer…!
many a time I also face problems with Javascript in IE and Firefox and Chrome.
———————————-
TheWebRipper
http://the4thdimension.com/
null is quite definitely an object,
much like 0 is a number.
do more reading, less writing!
Haha. Well Said.. (;
You are wrong about 2,3,5,6,7 and 9.
#9 is precisely why financial institutions (and sane institutions) don’t use decimal/float when dealing with money. There’s no such thing as fractional cents…you either have a cent or you don’t. It’s not a problem with JavaScript. It’s a problem with treating things that can’t be further subdivided as though they can be.
Oh dear lord, this article shows that you not only have a serious lack of understanding of Javascript but also programming and mathematics.
Envato need to start hiring competent staff. I see all kinds of kiddies and newby web developers idolising you. Do them a favor and get a clue before you make another post.
Yes, even I was surprised!
1 -> Is a pain only if you are seeing JS for the first time.
3 -> Why do you want to compare NaN anyway! There is a isNaN() function for that!!!
4 -> You quoted Crockford. He gives pretty neat solutions too!
5 -> Use a library, they handle it all. It anyways, is not a JS bug.
6 -> It’s unintuitive, yes; but extremely powerful.
7 -> That’s a mistake?? How??
8 -> “Maybe this isn’t specifically an error in JavaScript”
9 -> Oh come on! That’s what nearly EVERY language does. (In interpreted languages, I remember MIT Scheme does some neat stuff)
10 -> Then how will you code in Python?
I would add “no binary or byte array type”
this article is a non-sense, any language has a syntax, just learn it and apply it!
if you prefer coding in Java, use Java.