Why does IE nuke window.ABC variables?

etoleb picture etoleb · Jan 5, 2011 · Viewed 7.8k times · Source

When running the following block of code, FF and Chrome output typeof(hiya) = string while IE7/8 output typeof(hiya) = undefined.

<html>
    <body>
        <script type="text/javascript">
            window.hiya = 'hiya';
        </script>
        <script type="text/javascript">
            if( false ) {
                var hiya = 1;
            }
            document.write( "typeof(hiya) = "+ typeof(hiya) );
        </script>
    </body>
</html>

Each of the following makes the problem go away:

  • Combining everything into a single <script> block.
  • Removing the if block.
  • Renaming var hiya = 1 to var hiya2 = 1.
  • Renaming var hiya = 1 to window.hiya = 1.
  • Renaming var hiya = 1 to hiya = 1.

What is happening? Is there a scoping bug in IE?

Answer

Juan Mendes picture Juan Mendes · Jan 5, 2011

IE is dumb, it doesn't recognize that window.varName and var varName access the same variable in some cases.

When a new script tag is encountered, it first initializes all the variables declared with var. It doesn't run the var statement (the part that would initialize it to "hiya"). It just initializes it to undefined. It won't do that if it was previously declared with var though.

If your code was in a single script tag, this error would not happen. Also, if the first declaration of hiya was done with var, this error also wouldn't happen.

Specifically, in your second script tag, IE first looks for var statements, it finds a var var hiya = 1; Then it says, hiya hasn't been initialized with a var statements previously (IE being dumb, other browsers recognize that window.hiya does the same thing) and initializes hiya, overwriting window.hiya before executing any code.

Possible solutions:

  • Keep your code within the same script tag
  • Do not initialize variables with window.hiYa
  • If you don't control over one of the scripts, make sure the script that uses var comes first

Last note to clarify what JS parsers do to your code. When the JS parser sees your code, it transforms it into the following:

<html>
    <body>
        <script type="text/javascript">
            window.hiya = 'hiya';
        </script>
        <script type="text/javascript">
            // IE is dumb, it doesn't recognize that hiya is already 
            // defined as window.hiya, so it's initialized to undefined here
            var hiya;
            if( false ) {
                hiya = 1;
            }
            document.write( "typeof(hiya) = "+ typeof(hiya) );
        </script>
    </body>
</html>

So if you put everything into one script tag, this is what the code would be (after the JS engine moved the var statements to the top), so you can see that there is no way the IE could mess it up, since your window.hiya assignment would be after the var that was moved to the top.

<html>
    <body>
        <script type="text/javascript">
            var hiya;
            window.hiya = 'hiya';
            if( false ) {
                hiya = 1;
            }
            document.write( "typeof(hiya) = "+ typeof(hiya) );
        </script>
    </body>
</html>