Top 10 Things that JavaScript Got Wrong

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!

Math
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.

Add Comment

Discussion 130 Comments

Comment Page 1 of 21 2
  1. Chris says:

    Your first point is the best. I still correct people about that.

  2. 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.

    • Louis says:

      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.

      • Ben Cherry says:

        … 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)

      • Jeffrey Way says:
        Author

        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.

    • khaled says:

      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

    • I should correct myself. I’m not saying Jeffrey was wrong, I’m just saying it was extended from it.

  3. Revell says:

    Wow, this is some really interesting stuff! Certainly something to keep in mind when coding JavaScript for the next projects, thanks!

  4. Felix says:

    Good article! JavaScript is not perfect, do they have any plans on fixing this “bugs”?

  5. 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.

  6. anonymous says:

    Tell me in what language Nan == Nan/Nan === Nan ?

    • Paul says:

      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.

    • Paul says:

      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

  7. Louis says:

    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.

    • Jeffrey Way says:
      Author

      @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. :)

      • Louis says:

        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.

  8. 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 ;)

  9. Yada says:

    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()

      • James says:

        Agreed… it’s something you get used to. Doing “7″ + 4 is never a good idea anyway, even if your language does “support” it.

    • Joeytwiddle says:

      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

  10. Burak says:

    About #9:

    Try this in PHP:

    $num = .2 + .4;
    echo number_format($num, 20);

    It outputs: 0.60000000000000008882

    Number precision is an interesting subject.

    • Burak says:

      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.

      • Jeffrey Way says:
        Author

        Ahh good to know. Thanks for that explanation. :)

      • jmarreros says:

        Thanks david, I have always been asking why it happens.

      • tbmasood says:

        >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!

  11. salman says:

    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

  12. salman says:

    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

  13. Way says:

    Nice and interesting collection of javascripts shady side(s).

  14. Ganis Zulfa says:

    you know, you can make a global variable in js, just use ‘window.varname’, read it here > http://snook.ca/archives/javascript/global_variable

  15. Derrick Nelson says:

    #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.

      • David says:

        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 :)

  16. Ben Cherry says:

    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.

  17. Matt says:

    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.

    • James says:

      “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.

  18. thanks
    great informations and good tips

  19. Blogger Den says:

    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

  20. maSnun says:

    Great one! Thanks :)

  21. Thanks. Very useful stuff!

  22. Timothy says:

    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.

  23. Ywg says:

    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.

      • Ywg says:

        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.

    • Jeffrey Way says:
      Author

      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.

  24. Dean Landolt says:

    “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.

  25. Matt says:

    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).

  26. Abhijit says:

    # 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)

  27. Matt says:

    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.

      • Matt says:

        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.

      • Matt says:

        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.

    • Timo Reitz says:

      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.

  28. 46Bit says:

    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.

  29. 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 :)

  30. Edwin Martin says:

    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.

    • top says:

      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

  31. Grant says:

    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.

  32. 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.

  33. Kevin says:

    I am beginning to learn JavaScript and you just scared the hell out of me.

  34. Mikhail Poda says:

    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

  35. Daquan Wright says:

    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.

  36. Zecc says:

    #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.

  37. nuk says:

    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.

  38. 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.

  39. Francesco says:

    To solve the issue #9 you must use the toFixed() method.

  40. Also check out this new site which covers some more interesting “WTF’s”: http://wtfjs.com/

  41. Stick to using JQuery :) – even though knowing raw JS is important.

  42. Null being an object is a good thing.

  43. I guess nothing is perfect online, even the creator wished that he would not have used the double forward slashes…

  44. crstntnc says:

    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?

  45. andremoda says:

    Thank you very much. This Post is great LearningStuff.

  46. José Ramón says:

    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

  47. Yes, great post,
    What a fu*** Javascript ? http://wtfjs.com

    Regards,

Comment Page 1 of 21 2

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.