JScript Equality Operators, plus More On Mad Crushes

First, the technical stuff.  Here’s a recent question I received about missing data in JScript. 

I’ve seen it stated that in order to determine if a variable is undefined, you have to use if(“undefined” == typeof(x))
I attended a presentation on JScript today where the presenter used if(undefined == x)
When I asked about that, he stated that it works and he is not aware of any problems with it. Is he correct?

I discussed related issues earlier (here and here and here), but I figure that this is another opportunity for clarification.

There are three statements made. 

1) In order to determine if a variable is undefined, you have to use if(“undefined” == typeof(x))
2)  if(undefined == x) works
3) Mr. Presenter Guy is not aware of any problems with (2).

The first statement is demonstrably false because of that “have to” in there.  The typeof trick works, but “have to” implies incorrectly that it is the only thing that works.  This works just as well: if (x === undefined) (Note that triple equals in there.  More on that below.)

The second statement is also demonstrably false, because it has “false positives”.  Yes, this detects when a value is undefined, but…

var x = null;
print(x == undefined);

will evaluate as true, even though x is clearly defined!  undefined and null compare as equal to each other; this does not determine if a variable is undefined, it determines if a variable is undefined or is defined as a value which the comparison operator considers as equal to undefined.

The third statement was true; Mr. Presenter Guy was probably not aware of any problems.  I asked the original questioner to point out to Mr. Presenter Guy that the == operator gives false positives, so hopefully the third statement is also now false.

What the heck is up with the === operator?  Here’s the thing: the == operator is very lenient when comparing data of different types. 

print(“1″ == 1);  // true

 Which is often very useful.  But then one day (April 23rd, 1997, if you care) we added the switch statement to JScript and this question immediate arose: what the heck does this do?

x = 1;
case “1”: print(“string”); break;
case 1: print(“number”); break;

This switch statement in JScript is NOT logically equivalent to

if (x == “1”) print(“string”);
else if (x == 1) print(“number”)

because then this would print “string” when clearly the other case is by far the better match. 

The switch statement requires that not only must the case and the argument compare as equal, but they must also be of the same type. 

Given that, it would then seem really weird if you could construct a switch statement with these comparison semantics but could not construct the equivalent if statement.  Therefore we added the === operator, which has the same semantics as the comparator used in the switch statement.

This now explains why this works for undefined variables. The === operator checks to see whether the arguments are of the same type; since there is only one member of the undefined type, there can be no false positives.


In other news, I’ve managed to avoid the terrible fate that befalls boys who will not propose marriage.  No one will be exiling me to a desert island surrounded by sharp rocks and dropping hate-mail valentine cards from helicopters!  My erstwhile lovely girlfriend Leah is now my charming fiancée Leah, and I couldn’t be more pleased.  The plan so far is to get married next summer on the beaver-shark-infested shores of romantic Lake Huron, spend a week or so in romantic Holland, and then throw a huge yet elegant dance party back in romantic Seattle.

(UPDATE: Leah has just sent me an email saying that if anyone does exile me to a desert island, she will rescue me and then bake me that cake. That’s good to know.)

Comments (27)

  1. Legion says:

    Congratulations! I hope to avoid that terrible fate myself … but unless all the women I know are being insanely subtle (though after reading some of the mad crush advice, that’s not out of the realm of possibility), I’m not in the "at risk" demographic.

    Curiosity now begs the question … "What horrible fate befalls boys that propose marriage to the girls that don’t want it?" Hopefully it’s something nicer than being beaten up and exiled to a desert island.

  2. Hey, Mazel Tov Eric! May you guys have a long and wonderful life together.

  3. Shike Maffer says:

    Congrats Eric! Hope you and Leah will be very happy for years to come.

    Thanks for the insight into the === operator. I had a student ask about this, in the light of the fact that JScript is not typed, how can you compare object types? My response was for him sit down and get back to work on today’s lesson :-) or something equally as non-educating. I have sent him an email (he’s since graduated) correcting my error. Thanks again!

  4. Dan Shappir says:

    Congratulations Eric! As a ten year veteran I can honestly tell marriage is a good thing (my wife has yet to rescue me off a desert island, but she has baked me a cake).

  5. Eric Lippert says:

    > From step 3, I think this might allow for an exception

    I’m not following you. Step 3 of GetBase can only be executed if step 1 returns a reference. All references have a base object. There’s nothing in here that can produce an exception.

    Are you perhaps thinking of Step 3 of GetValue? Sure, that can throw an exception, but step 3 of GetBase ensures that GetValue is never called with a null reference.

  6. Steve says:

    Congrats! You never fully realize the "can’t live with them…" saying until you’re married. I wouldn’t trade it for the world and I’m sure you’ll feel the same way about yours.

  7. Nicholas Allen says:

    Hey, congratulations on making the big move!

    As an interesting Internet confluence, today we got a bug report from someone that "1" != 1 when they specified JavaScript version 1.2.

    The original JavaScript had type insensitive equality and the final ECMA standard v1 had type insensitive equality. However, Navigator 4 was based on a draft standard (along with a raft of Netscape extensions) and shipped with a type sensitive == and !=. This was JavaScript version 1.2 (1.0 and 1.1 correspond to the previous Navigator 2 and 3 releases). It lasted from late ’96 more than a year until Navigator 4.5 was released.

    The === and !== were added in JavaScript 1.3 and regular equality was changed back to the type insensitive version. Unless of course, you specifically ask for version 1.2.

  8. Eric Lippert says:

    Thanks all for your kind congratulations.

    Re: JavaScript 1.2 — indeed! Though I had forgotten the exact details, I certainly recall my colleagues who were attending the committee meetings in 1997 describing a certain amount of kerfuffle around this misfeature of 1.2. What a mess.

  9. secretGeek says:

    congratulations eric!

  10. sil says:

    Useful info on ===, thanks. As a corollary, which of these is better, in the sense of "won’t give an answer which is contrary to what I expect"?

    if (document.getElementById)


    if (typeof document.getElementById != "undefined")


    if (typeof document.getElementById == ‘function’)

    as a way of detecting whether a particular function exists? I tend to use 1, but it’s been suggested that 3 is better…

    Oh, and congrats on the engagement!

  11. Eric Lippert says:

    Well, the first says "is this property not null?" The second says "is this property defined?" The third says "is this property a function?"

    Which question do you want to ask?

  12. sil says:

    Heh. That’s sort of the point. What I want to ask is "does document.getElementbyId exist, and is it the DOM function that I’m expecting it to be?" Since, obviously, I can’t ask that specifically, which of your three questions is least likely to give me an answer that differs from the answer to my ideal question? There isn’t a clear answer to this, naturally; I’m more curious what you would use in that situation.

  13. Eric Lippert says:

    > does document.getElementbyId exist

    That’s easily done by any of the above, but the last is probably the most specific and therefore the most useful.

    > is it the DOM function that I’m expecting it to be?

    Hmm. Under what circumstances would it not be?

    I’m getting the sneaking suspicion that there’s a security question in here somewhere.

  14. Stuart Updegrave says:

    eric and leah —

    many many congratulations! i love the dance party idea … :)

  15. sil says:

    Oh, I wasn’t intending to pose a security question, really. At the moment, before I use any DOM code like document.getElementById() in a page, I bracket said code with if (document.getElementById). My question was more, "given the choice, which would you do?"

  16. Eric Lippert says:

    Got it. Because I can think of three reasons why a method might not be there:

    1) Because you’re maybe using some browser that doesn’t support it. In that case I’d recommend checking for browser version explicitly, etc.

    2) Because the property might accidentally be reset. Then a simple check would suffice.

    3) Because the property might be deliberately reset by hostile code that you didn’t write — like a script injection attack. In that case you have a very serious problem on your hands that would need careful threat modelling before we could begin to mitigate it.

  17. Nicholas Allen says:

    Ok, so let’s say malware.com has owned your document host object. What do they need your script for? They can inject or modify any content they want. It seems like they already have all the keys at this point.

  18. Eric Lippert says:

    Exactly! That’s why I wanted to make sure that the question wasn’t actually a security question. Determining whether any function actually does what you think it does is pretty much impossible if the environment is hostile, and it is pointless to try.

  19. Congrats on the engagement! May you two "live happily ever after!"

  20. Sathyaish Chakravarthy says:

    A hearty congratulations, Eric. Wish you a long, prosperous and blissful married life ahead.

  21. foxyshadis says:

    === is well known to any PHP programmer worth their salt. On the other hand, 6 years after inital implementation comments and questions about checking for type (or far more commonly, warnings about ‘mysterious’ failures when checking a return value for false when it can be int/string or false on failure, and the ugly workarounds for it) still regularly pop up, even from fairly knowledgeable people who never felt the need to learn how their language of choice differs from C/C++/Java. This and other background differences is probably one of the major pitfalls of giving an untyped language a familiar C family typed syntax.

  22. Roy Sharon says:

    I think that the "undefined" thing has a more subtle behavior. Compare the following two programs.

    Program #1:

    var foo;

    if (foo === undefined) var bar = 1;

    Program #2:

    if (foo === undefined) var bar = 1;

    Program #1 will run fine, resulting with bar==1. But program #2 will crash (try it!), because foo is undeclared when the if statement is reached. The *only* safe way to avoid this is doing:

    if (typeof(foo) == "undefined") var bar = 1;

    Program #2 may also be made to run by putting somewhere in it a declaration of foo:

    var foo;

    This way, when the if statement is reached, foo is already declared, and is equal to undefined.

    BTW, declaring foo does not change its value, so you can safely do it even if you’re not sure whether foo was previously declared. The only concern here is that declaring it inside some scope (such as a function), will make it a local variable, overriding a variable with the same name from a surrounding scope.

    BTW, there is a nice idiom that uses this technique to add a default value in case foo is undefined:

    if (foo === undefined) var foo = 3;

    The if statement will not cause a crash, because the parser collects all var declarations before executing the script, so foo is already declared when the if is reached.

  23. Eric Lippert says:

    Excellent point, Roy. I hadn’t considered the fact that typeof does not activate the "undeclared variable" logic.

  24. I’ve talked a few times in this blog about the semantics of the equality operators in various languages….

  25. Mark says:

    I think that the code

    if(x === undefined)

    is actually testing that the variable named "x" is strictly equal to the variable named "undefined". undefined is not a keyword, so a declaration such as

    var undefined = true;

    is perfectly legal. This declaration would obviously break the strict equality test, so I think that

    if(typeof(x) == "undefined")

    is really the only "correct" way to do this test.

    Sorry to post a comment so out of date, but I just recently discovered your blog and have been enjoying reading through your old posts.

  26. EricLippert says:

    You are correct, and I should have called that out in the post.