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.

Your first point is the best. I still correct people about that.
Same…
JavaScript is actually called ECMAScript.
http://en.wikipedia.org/wiki/ECMAScript
The content-type text/javascript means moot, simply because there is no such thing as Javascript. But since its so widely used, they have to leave it.
Actually, that’s not exactly correct. What Jeffrey says in the article is more accurate.
To quote the Wikipedia article you linked to:
“Both JavaScript and JScript aim to be compatible with ECMAScript, while providing additional features not described in the Ecma specification.”
Thus, JS is based on ECMAScript, but is not synonymous with it.
There is such a thing as JavaScript. JavaScript is an implementation of ECMAScript, just as ActionScript is an implementation of ECMAScript as well.
Fun fact: the ECMAScript standard came about from Netscape submitting JavaScript 1.1 as a proposed new standard.
… and the reason they didn’t just call it JavaScript was because Sun owned the trademark “JavaScript”, and only Netscape had the license to use it. Thus the terrible, terrible name ECMAScript (which was the working name while the standard was being drafted, but was never meant to be the final name)
Another interesting note is that JavaScript was originally called LiveScript. In fact, Netscape “owned” the word “Live.” As they disappeared, it then became Microsoft’s…which is why you see all of their Live services now.
Interesting (about Live). I wonder what they’d call their Live services if they still couldn’t use Live.
@ Jeremy: How about “Slow”, as all their services are terribly slow, not really “Live” :P.
JavaScript is not ECMAScript but it is based on EcmaScript Like ActionScript 3.0 in Flash You will find ur self very fimiliar with this language if you are a javaScript Dveleoper
ActionScript 2.0
I should correct myself. I’m not saying Jeffrey was wrong, I’m just saying it was extended from it.
Wow, this is some really interesting stuff! Certainly something to keep in mind when coding JavaScript for the next projects, thanks!
Good article! JavaScript is not perfect, do they have any plans on fixing this “bugs”?
Yes, but it’ll take a while.
I propose that all browsers start using Ruby instead. Starting tomorrow.
No! I’ll lose my JQueryz!
Extending #9
Javascript often misidentifies numbers as strings and will concatenate instead of adding.
10 + 1 //output 101
I sometimes use multiplying integers by 1 or I’ll use parseInt()
I can’t say I’ve ever seen that. Number + number has always resulted in an arithmetic operation. It’s when you obtain a value, say the opacity of an element using getComputedStyle(), that’s a string value that you end up seeing concatenation.
Tell me in what language Nan == Nan/Nan === Nan ?
That’s the point I was going to make. NaN comes from floating point math and is actually a range of possible bits that don’t map to an actual number. The problem in comparing NaN === NaN comes from the IEEE definition of floating point. Imagine A + A, the result is 2A. If A = NaN, then you would have 2NaN. But you can’t do that, so the result of NaN + NaN is NaN (not 2NaN). So NaN + NaN !== NaN, simplified is NaN !== NaN.
That’s the point I was going to make. NaN comes from floating point math and is actually a range of possible bits that don’t map to an actual number. The problem in comparing NaN === NaN comes from the IEEE definition of floating point. Imagine A + A, the result is 2A. If A = NaN, then you would have 2NaN. But you can’t do that, so the result of NaN + NaN is NaN (not 2NaN). So NaN + NaN !== NaN, simplified is NaN !== NaN.
P.S. Had trouble posting in Chrome 5.0.307
Nice little roundup of info, although some of it is really quite trivial in most cases.
Just a quick question:
I’m not entirely sure why, under “Code Styling Isn’t Your Choice”, you said: “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.”
Why wouldn’t you have control of the code?
Thanks.
@Louis – Maybe that came out wrong. I just meant that it’s really strange when simply placing the curly brace onto its own line could cause such a bug…one that can be really confusing to understand at that. :)
Ah, I see. I just read it again. You were saying that because the brace is on the wrong line, it makes you lose control of the code, when it shouldn’t because technically it’s not a syntax error. Thanks, makes sense.
If you correctly finish lines of code with a semi-colon wouldn’t that resolve the issue?
In other words, if you had return on one line and the curly braces on the next line but you still had a:’b'; <- with semi-colon, will JS still insert a semi-colon after the return?
This sort of thing in doesnt seem to matter with loops and if/else, etc… so it would seem there are some style choices.
No, the issue can still occur. The problem is JavaScript will insert the semicolon before the opening curly brace on the next line.
coould you do this?
return//
{
something;
}
thus commenting out the added ;?
Not that this is at all practical. I’m just curious.
No. JavaScript still inserts the semi-colon after return.
Semicolon insertions was also done really poorly and as Crockford says “should scare the hell out of you.” Great list Jeff, perhaps a follow up of “Top 10 Things Javascript Got Right” would be a nice comparison, though I have no doubt you already have something up your sleeve ;)
Using + as string concatenation was a huge mistake. PHP got it write with .
’7′ + 4 gives ’74′
whereas
’7′ – 4 gives 3
I don’t see anything wrong with using the additive operator for concatenation. JavaScript isn’t the only language that does. Once you know the behavior, you can predict it and get around it with parseInt() and parseFloat()
Agreed… it’s something you get used to. Doing “7″ + 4 is never a good idea anyway, even if your language does “support” it.
Javascript:
’7′ + 4 => 74
’7′ – 4 => 3
You can use |0 as a shortcut to turn a string into a number, e.g.:
(’7′|0) + 4 => 11
About #9:
Try this in PHP:
$num = .2 + .4;
echo number_format($num, 20);
It outputs: 0.60000000000000008882
Number precision is an interesting subject.
Also, PHP has the bcmath library for high precision operations:
echo bcadd(.2 , .4 , 20);
outputs: 0.60000000000000000000
I’m not sure if JS has something built-in like that.
The reason why this happens is that it internally converts every number into the dual system (base 2) before performing operations like addition, substraction etc. The problem with that is, that numbers which only have one digit in the decimal system could be periodic in the dual system. Because periodic numbers seem to be rounded, such funny results can appear. It’s the same as calculating 1/3 + 2/3 in a dumb calculator and getting 0.99999999999 as result.
Ahh good to know. Thanks for that explanation. :)
Thanks david, I have always been asking why it happens.
>The problem with that is, that numbers which only have one digit in the decimal system could be periodic in the dual system.
Right.
e.g. in plain old binary representation (not IEEE format),
0.2 = 0.001100110011….
0.4 = 0.011001100110011….
0.6 = 0.1001100110011….
See the repetitive pattern!
very very usefull
jeff im language i should say “good man the laltian”
my might understand this but good work to keep us informed about the dark aspect of js
thanks again
very very usefull
jeff in my language i should say “good man the laltian”
you might not understand this but it means “man you are doing good work”.
keep us informed about the dark aspect of js
thanks again
Nice and interesting collection of javascripts shady side(s).
Thanks Jeff!
you know, you can make a global variable in js, just use ‘window.varname’, read it here > http://snook.ca/archives/javascript/global_variable
Right – or simply leaving off var will automatically make it a global variable…but we don’t really want that. :)
Oops. Beat me to it by a few minutes =)
You don’t have to use the window prefix; simply omit the var keyword and you have a global variable. However, you want to avoid globals as much as possible.
#6 isn’t an error; it’s expected behavior.
Javascript passes functions by reference. In the case of foo(bar.method), you’re passing a -static- reference to the function. In PHP, here’s what your example looks like:
$bar = new Bar ();
$bar->method (); // echoes “Hello, World!”
foo ( Bar::method () ); // passing static reference to method; produces fatal error telling you $this doesn’t exist because there’s no object in scope
Hope this helps. Interesting article.
Expected behavior, yes. But the article was what is wrong with the language.
Many languages allow you to pass methods while keeping the link between method and object intact. At some point, everyone expects JavaScript to keep this link and tries it.The most common workaround, wrapping the method call in an anonymous function, is awkward and can be the source of memory leaks done incorrectly. Expected, but wrong, behavior.
I’d like to mix #4 with #6.
You can really create javascript that never creates global variables. Thanks to the hidden scope that you describes in point 6.
This is the biggest advantage of JS. When creating a website you have the choise to implement different scritps to a page, not harassing each other…
Anyhoe, Closures rock in JS, once you get used to them :)
Nice post, but I have to take issue with #6, #9, and #10.
#6: I really don’t like the idea that a function should “remember” its parent. I like that a function can be be passed around between objects and not need to remember who created it. I think this is done right. There are other problems with function context, like ‘new’, but this example is not one of them.
#9: Try that in almost any language, you’ll get the same result. I don’t know why this surprises so many people, and is indicative of a failure of the language. I will admit that JavaScript should have integers, but floating point arithmetic is inexact in every language. This is not a JavaScript problem.
#10: I don’t think that allowing formatting however you’d like is necessarily a great thing. Languages like Python are a bit overboard, but I don’t think the headline “Code Styling isn’t your Choice!” really captures the essence of the problem here. The problem is semicolon insertion. That return behaves badly when you use an object literal on the next line is merely a symptom of the disease.
Any 10-things-I-hate-about-JavaScript list absolutely HAS to include the effed-up ‘this’ operator. It is without question the worst thing I have seen in any programming language ever.
Yes, including PHP.
It’s bad.
“this” isn’t an operator; it’s just a rudimentary “value”, sometimes called a “keyword”.
I don’t see what’s wrong with it. How else would you like to reference an instance of a class from within one of its methods?
> How else would you like to reference an instance of a class from within one of its methods?
Like so:
(If the formatting doesn’t come through, I’ve written more about this style at http://jonaquino.blogspot.com/2009/08/public-and-private-methods-in.html )
/**
* Behavior for the forum/category/edit page.
*/
xg.forum.category.edit = function() {
/** Container for public functions. */
var self = {};
/** Container for private functions and variables. */
var _ = {};
/**
* Constructs the object.
*/
_.initialize = function() {
// This is the constructor
};
/**
* Foo foo foo.
*/
self.foo = function() {
// This is a public method
};
/**
* Bar bar bar.
*/
_.bar = function() {
// This is a private method
};
_.initialize();
return self;
});
Note from this example that you refer to public methods using self.foo() and private methods using _.bar(). Unlike “this”, self and _ always work from any context.
Many OO languages incorporate the this keyword. this isn’t a problem.
You must use a JavaScript class to use this properly, thats the only instance.
thanks
great informations and good tips
For what it is, JavaScript is a very useful and productive scripting language. Granted everything has it’s ups and downs, but overall it is very useful. Awesome article, I’ll have to submit it to Blogger Den to see if you can get any good traffic
Great one! Thanks :)
Thanks. Very useful stuff!
1) True, but not completely. The name JavaScript was used to ride the success of Java, but it is actually ECMAScript on most engines. Except on same, like on IE it is JScript.
2) Null being an object can be very useful. Doesn’t mean it’s ‘wrong.’
3) Try NaN == NaN
4) Ya, that is a problem. Everything is global, unless if you make vars available only within a function, or withing (function() { })();
5) This applies to anything that uses user-agent strings. PHP, Ruby, etc.
6) Scope – you have to bind. The ‘this’ object is powerful. Once again, I wouldn’t consider it ‘wrong.’ It’s how the language works.
7) Ok, not really ‘wrong,’ but not right, i suppose.
8) use ===
9) Google (they may have fixed this) does similar things with arithmetic. And many languages do too. Memory allocation issues limitations.
10) Browsers are forgiving. Meaning that you can throw poorly written HTML, CSS and JavaScript at it and they will try their best to make it work. This is a good and bad thing. Good thing is that you can do things in different ways and have the same outcome. Bad thing is that you can write poor code and have it work. The semicolon insertion is determined by the JavaScript engine being used, and is done to attempt to correct poor code, thus attempting to be forgiving. Sometimes it just doesn’t work as you predict. You should write good code in the first place, so I don’t mind this flaw.
Seems like you compared JavaScript to Java often in this post. Not completely fair since Java is on a whole different medium, thus is a whole different type of animal.
And do remember that JavaScript has been around for a long time, and like any old language it has problems. Look at PHP. PHP is pretty ugly, but has been extended upon greatly. So it has improved in functionality. Whereas with JavaScript most browsers are still on version 1.5, whereas Mozilla is on (i think) 1.8. But you can’t use 1.8 syntax until all major browsers support it. So improving the language is hindered.
Forgive the 8) – I put in 8 ) without the space and it thought it was an emoticon
Great points, Timothy. :)
You got some points wrong :
3 – NaN, I don’t see any problem here, every language with a NaN act like that. Consider the following : you’ve got an algorithm expecting numbers, for whatever reason you end up with contamùinative NaN values, do you wan’t your comparisons to be truthy ? No, NaN is a falsy value.
5 – As you said, not javascript related. It’s a browser issue.
6 – Scope inconsistencies : I don’t see any inconsistency, “this” is (as you expect) a context dependant value. You call your method from two different contexts, you end up with two differents this values. It’s just perfectly logical, and again, every other programming language with the this keyword works exactly the same way.
7 – You got the general point good, but what’s with this sentence “Consider the first item, &; it would be much more efficient to use the && operator, as it’s quicker.” ??? Bitwise AND and logical AND are not the same operator, comparing them (or their speed) do not make any sense as they don’t achieve the same operations.
9 – Not a javascript issue, it’s a computer science issue. Computers can only do finite operations, they can’t handle floating point operations. We, humans, build abstracts constructs on top of theses finites operation to emulate floating point numbers, there is no solution to this problem. The best we can do is build more complex abstractions which can give us more precise result, but at some point we will always reach the model limit. And once again IEEE754 (aka Double) is the most common numeric abstaction, almost every programming language implement it, and have the same flaw.
In reference to your statements in #6:
First, no, it’s not logical. Nearly everyone, at one time or another, has tried something like the following code:
var _get_ = document.getElementById;
var el = _get_(“elementId”);
The code reads “assign the getElementById method of the document object to the _get_ variable”. Therefore, it’s logical to assume that _get_ is now a delegate and functions exactly like document.getElementById.
Second, your assertion that every language with a this, or equivalent, keyword works the exact same is false.
Your right, everyone has made this mistake one day or another. I tried it, got it wrong, but that do not mean that this is a flaw in the language.
This, represent the current execution context. You call a function in the context of the document object, this equals the document object. You call the same function from the global object, this equals the global object. It just make sense.
It may be a little tricky, but it’s logical.
As for my assertion, as far as I know, this is true for every language I ever used.
If you know a language where the this keyword get statically binded at parse time, please post an example, I’ll be happy to extend my knowledge.
Citing that “everyone does it” is proof that it’s more logical that JavaScript keeps that link between object and method than dropping it in favor for whatever context the method is assigned to. You can’t get any more logical than how the code reads.
The point is that no matter what the context you assign a method to, JavaScript should keep the method attached to the object/context that it actually belongs to. The only exception should be global/window. We have operator precedence – why can’t we have object/context precedence?
C# keeps the link between object and method intact. I assume Java does as well.
Hey Ywg –
About #7 – Maybe that came across wrong when I wrote it. I’m aware that the single & will evaluate both arguments, while && will only evaluate the second argument if the first is true. What I meant is that I suspect that when people use &….they’re really meaning to use &&.
But maybe I’m wrong.
“This is just wrong. Instead, if you want to determine if a value is indeed NaN, you can use the isNaN() function.”
This is bad advice. Technically NaN !== NaN is correct but isNaN should *definitely* be on this list! The safe and correct way to test for NaN:
var x = NaN;
(x !== x) === true;
NaN is the _only_ thing in the language with this behavior.
Number 6 actually makes sense to me. I don’t know why, but it does.
Number 9, though, isn’t just JavaScript. MANY languages have difficulties with pointer arithmetic, and it has to do with the binary conversion of it.
For instance, depending what processor you have, doing an arithmetic operation of 0.5 * 2 in assembler may return 0.99999999999 or 1.000000000000001 depending on how your system rounds numbers. It could be as bad as the system doing [|x|] = 0.5 * 2, returning 0 (very, very rare).
# 8. I feel your examples actually show how “falsy” values should be checked. If a beginner is taught that then there should not be any confusion
This means instead of doing something like
if (value == null) or if (value == false) or if (typeof value == undefined) etc.
Just do
if (!!value)
Yeah – this is true.
What’s with the “!!”? It’s superfluous, since the if statement tests for “truthy’ness” — it doesn’t require a boolean.
It doesn’t directly have to do with the points posted, but it just seems odd to me.
Doing console.log(true + 1); will return 2. In just about any other language, true + 1 will either throw an illegal cast or keyword has no operator. Javascript, on the other hand, treats true as a Number.
It’s not so much that it treats true or false as a number, but that JavaScript tries to be smart and coerces the operands based on the operation.
Hey there Jeremy McPeak, just wanted to say, love your work.
Here’s the thing, though. Where is JavaScript deriving that true is equivalent to one when cast as a Number, and likewise false is equivalent to 0? I mean, Boolean operators only use 1 and 0 as pseudo ways of defining the connection between true and false, but is in no way an actual representation. It (kinda) makes sense to me if true were to equal any real number set in an empty space (like when you reference an uninitialized integer in C) and false would equal either 0 or null. This would assume that there was no definite representation of true or false, only something and nothingness.
What would make great sense, at least, would be if true and false were cast into NaN values, defining console.log(true + 1) into console.log(NaN + 1) returning NaN, since true and false, theoretically, have no numerical representation.
I think that’s coming from my “I don’t want my language making assumptions for me” personality. :P
Thanks, Matt =)
At the most basic level, and I’m strictly talking about theory, a Boolean value is simply one bit. When the bit is on (1), the Boolean value is true. When the bit is off (0), the Boolean value is false. So I can see where the values of 1 and 0 comes from when Boolean is converted to a Number; convert that bit to number and you get either 1 or 0.
At least two other languages, Python and PHP, do this as well. And know, I don’t like this behaviour either, because the decision wether true equals 1 and false equals 0 is arbitrary, it would work the other way around just as well.
Oh, and in VBscript, in a number context, true is -1 and false is 0.
Whilst at first the NaN thing might seem wrong, I’d say that that statement shouldn’t even be run without errors. NaN implies ‘not a real number’. Now for those of you not familiar with this, you can use the square root of -1 as i – this brings up the whole field of Complex numbers etc. 5i != 2i, yet both would be interpreted as not a number. Whilst I appreciate this isn’t what javascript is supposed to handle, this testcase only proves that every complex number doesn’t equal every other complex number.
Considering point number 3: NaN !== NaN
This is actually a GOOD thing. At least from a theoretical mathematical point of view. Consider this:
var a = 4/0; // a is NaN
var b = 3/0; // b is NaN
Are a and b equal? No, they are not. Yes, they are both a ‘kind of’ infinity, but they are not the same.
I can understand why it would be useful in a programming language to treat them the same (after all, they are both ‘meaningless’ in computing terms), but they are NOT the same.
While I agree that is it not USEFUL to have a!=b, it is certainly TRUE that a!=b. So I would argue that this is not a thing which JavaScript got wrong – it’s right – it’s just unexpected :)
This, at least in JavaScript, is wrong.
4/0 is not NaN, but Infinity, and 3/0==4/0 is true in JavaScript.
1. You can always call it ECMAScript if you want.
2. What’s the problem? It has to be something.
3. Is unknown person A always equal to unknown person B? No. There you have the reasoning behind it.
4. It’s a bit sad that variables without the ‘var’ keyword become global. You adding ‘var’ solves this. And using global vars is not required. You can do (function(){var a; /* do your stuff here */})() to keep the global space clean.
5. Pff. Nothing to do with JavaScript. Use navigator.appName.
6. Also not a JavaScript-problem, but just OOP-basics. A method has to know on which object it operates, otherwise the object will be window, the global object.
7. And what’s wrong about this? If you want to use bitwise operators, you can do it.
8. I think all scripting languages behave this way, because it’s common sense and very handy. It’s so much easier to write if(str){…}.
9. JavaScrips has standardized on IEEE floating point variables. The advantage is that many computers know exactly how to deal with them. The unfortunate disadvatage is rounding errors. You just have to use Math.round() to deal with them.
10. I think the creator of JavaScript couldn’t decide whether or not every statement should end with a semicolon. It choosed both ways. In some very rare, obscure ambigious code this could lead to unpredictable results. I learned about the semicolon-appending behaviour when I learned JavaScript. Just as it should have.
JavaScript has some behaviours which, at first sight, seems peculiar. They are just design decisions. JavaScript is not PHP of Java of C so don’t expect it to be. Learn how JavaScript works and you’ll find it’s a very nice language.
very nicely written..
The article seems like complaint of java developer… When working with javascript or any scripting language, you also need to change your mind set.. which can be difficult in the beginning
Issues like this are the reason that javascript can really mess up a site if not implemented properly. With it being such a flaky language, using it to power essential page elements like navigation menus is risky, and generally bad practice. Javascript can quickly become a nightmare when writing more complex functions.
NaN = infinity
in math you CAN’T say that infinity is equal to infinity, because this would lead you to:
infinity – infinity = 0
infinity/infinity = 1
1^infinity = 1
0^infinity = 0
and so on….
All operations above don’t have a result, they’re undefined.
No, in JavaScript NaN != Infinity, but Infinity==Infinity.
Nice tutorial
See, this is why we need a ( REPORT ) button.
The links are nofollow so it hardly matters…
But it’s more (off topic) spam to sift through to meaningful responses. I mean, I have to problem with “Good Article”, but when the post has nothing to do with the subject, well, it’s annoying.
Or maybe a rating system like Digg
But that’s also not the best solution. Because some comments get hidden just because people disagree, not because it’s low-quality or spam.
I am beginning to learn JavaScript and you just scared the hell out of me.
NaN behavior of JavaScript complies with IEEE 754 (IEEE Standard for Floating-Point Arithmetic), see http://en.wikipedia.org/wiki/NaN
Summary:
NaN === NaN must return FALSE after IEEE 754
smap
I know little about the language (do a bit of scripting in firebug/editors from time to time), but it’s so nice to see the bad things in a language. As someone says, you can’t build something good made out of something bad (unexpected things happening).
Nice post.
#4 “The dependence upon global variables is widely considered to be far and away the worst part of JavaScript.”
What?
Ok, so undeclared variables are considered global by default, and that’s a real problem, but JavaScript doesn’t depend on global variables *at all*.
And if people think it does, then they are just bad programmers.
Some of the best minds in JavaScript would disagree with you, I’m afraid.
You are right in most points, but definitely wrong in others.
Points in which I disagree:
NaN != NaN makes good sense.
Why, you ask? For the same reason for which infinity is not equal to itself. It’s a symbol, not a value.
Floating point precision is my next point. If you had the slightest idea on how floating point representation works, you had shut up. Or, rather, as you criticize it, name a programming language where this is _ NOT_ the case. Floating point comparison is never done by “==” but always by “if (Math.abs(value1 – value 2)) < 1e-10 { foo(); } ". (Ok, I admit, this isn't JavaScript, as I don't know how the absolute value is computed in JavaScript, so I just wrote the first thing that came to my mind – Java)
And, if you are right about the point that the bitwise operators work just as in Java, then what you said is rubbish. Bitwise comparison hasn't got anything to do with comparison. Using them in such cases is bad programming style and not something bitwise operators are intended for. Bitwise operators perform bitwise operations, and nothing else.
And then, your last point. The one with semicolon insertion. Well, shit in shit out. The second statement is not unambiguous! You create a map (mapping 'b' to the index a), and before that, you have a return statement. Now – do you wish to return nothing and create a map, or do you want to return the map? See what JavaScript thinks? This semicolon insertion thing still is something I don't like. Generally, when computers try to be clever, they are not.
And for point 8 — what is wrong about different values that to human understanding mean "no" be equal to false? You might want to do some comparison stuff on lots of different data types, so why not allow a value being equal to false?
And finally, null being an object can be handy at times. It may confuse your logic, but it still makes sense.
In the third line, I ment NaN !== NaN of course.
IEEE says that a figure is saved this way: (-1)^S * (1.M) * 2 ^ (E – 127)
Where the 32 bit of memory are split up in following way. S is one bit long and indicates if the figure is negative or not. M is a 23 bit long binary number. And E is 8 bit long.
With this in mind it should be clear that there are no “clean” float figures / operations at all. There are always some digits in the far back, and that’s why == comparison doesn’t work with floats.
And that’s in every programming language the same.
To solve the issue #9 you must use the toFixed() method.
Also check out this new site which covers some more interesting “WTF’s”: http://wtfjs.com/
Stick to using JQuery :) – even though knowing raw JS is important.
Null being an object is a good thing.
I guess nothing is perfect online, even the creator wished that he would not have used the double forward slashes…
now i understand this is supposed to be fun but… there’s a lot of nonsense here…
for example the NaN stuff
if 2 things are not numbers, this means that they are supposed to be equal? what’s so funny here?
Thank you very much. This Post is great LearningStuff.
It’s sad when people get upset at this, being aware of this stuff and have a little laugh about should be the best :D
Yes, great post,
What a fu*** Javascript ? http://wtfjs.com
Regards,