IE javascript bug: global variable

M

mikewse

I came across this strange little bug in IE 6 and 7, described below.
Does anyone know if it has been reported before and where it may be
possible to find more information about it?

Description
-----------
Two script blocks in a page. The first block assigns a global variable
though "window.myObj" syntax. The second block queries it without
window prefix. It works as expected as long as the last line is not
uncommented. Uncommenting the referred if-statement causes the "myObj"
definition to disappear from the second text block and alert(myObj)
will show "undefined" although executed before the uncommented
statement.

<script type='text/javascript'>
window.myObj = {};
alert( myObj );
</script>

<script type='text/javascript'>
alert( myObj );
// the following line causes myObj == undefined !
// if (myObj == null) var myObj = {};
</script>
 
D

Doug Gunnoe

I came across this strange little bug in IE 6 and 7, described below.
Does anyone know if it has been reported before and where it may be
possible to find more information about it?

Description
-----------
Two script blocks in a page. The first block assigns a global variable
though "window.myObj" syntax. The second block queries it without
window prefix. It works as expected as long as the last line is not
uncommented. Uncommenting the referred if-statement causes the "myObj"
definition to disappear from the second text block and alert(myObj)
will show "undefined" although executed before the uncommented
statement.

<script type='text/javascript'>
window.myObj = {};
alert( myObj );
</script>

<script type='text/javascript'>
alert( myObj );
// the following line causes myObj == undefined !
// if (myObj == null) var myObj = {};
</script>

Yet this works:

<script type='text/javascript'>
window.myObj = {};
alert( myObj );
</script>

<script type='text/javascript'>
setTimeout("alert( myObj )", 1000);
// the following line causes myObj == undefined !
if (myObj == null) var myObj = {};
</script>

I'm sure that more of the technically minded individuals in this group
can give you a better answer, but here is my guess.

In the 2nd block the script calls alert. It does not wait for alert to
complete of course, it just goes on to the next line. By the time
alert executes, it has declared 'var myObj', which of course is local
and not the same as your global myObj, but has not yet completed the
assignment operation (= {}). Thus the local myObj is undefined.

Guessing is so much easier than actually investigating the problem.
lol.
 
H

Henry

I came across this strange little bug in IE 6 and 7, described
below. Does anyone know if it has been reported before and
where it may be possible to find more information about it?

Description

Strictly that is not a global variable; it is a property of the global
object. Global variable declarations result in properties of the
global object with the internal - DontDelete - attribute set, while
properties of the global object created through assignment can be
deleted.
The second block queries
it without window prefix. It works as expected as long as the
last line is not uncommented. Uncommenting the referred
if-statement causes the "myObj" definition to disappear from
the second text block and alert(myObj) will show "undefined"
although executed before the uncommented statement.

<script type='text/javascript'>
window.myObj = {};
alert( myObj );
</script>

<script type='text/javascript'>
alert( myObj );
// the following line causes myObj == undefined !
// if (myObj == null) var myObj = {};
</script>

Presumably you are unaware that in javascript all variable
declarations and function declarations are acted upon during variable
instantiation for the pertinent execution context and so precede the
actual execution of code in that context. This renders the position of
your - var - declaration irrelevant as it is acted upon before the -
alert - call in the second SCRIPT element is executed. By 'acted upon'
I mean the declaration is acted upon, not the corresponding
assignment, as that must wait for the line of code to be executed.
That is why the actual value displayed in the alert is undefined, as
variable instantiation defaults variable values to undefined when it
creates the variable (and pending assignment while the code later
executes). Javascript is not block-scoped.

Yes that is a bug. It is a violation of the second sentence in the
paragraph for/on VariableDeclarations in Section 10.1.3 of ECMA 262
3rd Ed. Unfortunately the third sentence seems to back-track a little
on the second and so this may be a result of JScript's authors giving
that more weight. Then again ECMAScript was not really defined with
sequences of separate global execution contexts in mind so this is the
sort of area where specification interpretations are likely to result
in differing behaviour in different implementations.

Declare all of the global variable you are going to use prior to
referencing them and you won't have any issues resulting from this bug.
 
D

Doug Gunnoe

This renders the position of
your - var - declaration irrelevant as it is acted upon before the -
alert - call in the second SCRIPT element is executed. By 'acted upon'
I mean the declaration is acted upon, not the corresponding
assignment

So basically Henry confirms that I was almost right. Joy. :)
 
M

mikewse

Strictly that is not a global variable; it is a property of the global
object. Global variable declarations result in properties of the
global object with the internal - DontDelete - attribute set, while
properties of the global object created through assignment can be
deleted.

Ah, thanks, I didn't realize there was a difference between these two
ways of creating a "global variable" (property of the global object)
and have been using them interchangibly.
Presumably you are unaware that in javascript all variable
declarations and function declarations are acted upon during variable
instantiation for the pertinent execution context and so precede the
actual execution of code in that context.

I was actually aware of this, and among other tests have seen that
removing "var" (leaving just the assignment) also works around the
bug.
But with a correct/"bug-free" implementation I should be able to use
the global.property and var syntaxes interchangibly, right?
Yes that is a bug.
Then again ECMAScript was not really defined with
sequences of separate global execution contexts in mind

That's another aspect of this bug that puzzles me; all global code in
the first block should "run to completion" before the second block is
entered. Specifically, both variable instantiation and actual code
execution in the first block should come before variable instantiation
of the second block. But parts of this bug makes me think that IE runs
some part of the variable instantiation in the second block before
code execution in the first block as it comes to the resolution that
the variable needs to be initialized.
This is contradicted though by testing to merge the two script blocks;
the bug doesn't show itself in this case.
Declare all of the global variable you are going to use prior to
referencing them and you won't have any issues resulting from this bug.

The scenario is more complex than outlined as I just provided the
simplest possible code to describe the bug. Specifically, it's about
nested variables x.y.z (hindering the use of var declarations) and the
inclusion of separate script files (therefore the two script blocks).
But with knowledge of the bug's anatomy it will be possible to work
around it.

Thanks for your help!
 
G

GArlington

I came across this strange little bug in IE 6 and 7, described below.

This is NOT a bug, and never was or will be a bug.
Does anyone know if it has been reported before and where it may be
possible to find more information about it?

Description

Here you define page-global (global for ALL scripts on the page) var
myObj
The second block queries it without
window prefix.

You can access the above global var with or without "window." prefix.
It works as expected as long as the last line is not
uncommented. Uncommenting the referred if-statement causes the "myObj"
definition to disappear from the second text block and alert(myObj)
will show "undefined" although executed before the uncommented
statement.

When you uncomment the last line, you basically tell the function that
you intend to define AND use function-local version of var myObj. So,
when you try to use it (in your alert()) before you assign any value
to it - it is "undefined".
This is the way ALL functional programming languages work, you can
always re-define the var within the function/scope.
 
D

Doug Gunnoe

I was actually aware of this, and among other tests have seen that
removing "var" (leaving just the assignment) also works around the
bug.

That's because when you use 'var' here you have created a completely
different and local variable named myObj. So you are trying to do an
alert on your global myObj and instead are passing it the local var
myObj.

If I understand what Henry is saying, your declaration 'var myObj' is
taken care of first in your block of code, regardless of where in the
code you place it. And this makes some sense considering that local
variables have scope throughout the block.

But the assignment operation does not happen until the order in which
it occurs. Therefore, alert(myObj) displays undefined on your local
myObj var that has not yet been instantiated.
 
D

Doug Gunnoe

That's because when you use 'var' here you have created a completely
different and local variable named myObj. So you are trying to do an
alert on your global myObj and instead are passing it the local var
myObj.

Cripes. I just noticed your example is outside any function{} so the
var declaration would be global anyway.
 
H

Henry

On Feb 18, 2:33 pm, GArlington wrote:
When you uncomment the last line, you basically tell the function
that you intend to define AND use function-local version of
var myObj. ...
This is the way ALL functional programming languages work, you
can always re-define the var within the function/scope.

There are no functions in the posted code.

The specification says that acting on a variable declaration should
not alter the value (or attributes) or a pre-existing property of the
Variable object and the posted code demonstrates that happening, so it
is a bug.
 
M

mikewse

@Doug and GArlington
Note that the code example only references the global scope as it is
not defining any functions. Thus, there are no local scope or local
variables to get confused with.
If you still think what is described is not a bug, then you may want
to look at what Mozilla/Firefox is doing as they behave the way I (and
probably Henry and Randy) would expect.
 
H

Henry

Ah, thanks, I didn't realize there was a difference between
these two ways of creating a "global variable" (property of
the global object) and have been using them interchangibly.

So long as you never attempt to delete either you will see little or
no practical difference.
I was actually aware of this, and among other tests have seen
that removing "var" (leaving just the assignment) also works
around the bug.

Falling to declare what are effectively global variables does have the
effect of provoking another IE behaviour; in that IE creates a
property of the global object for each IDed element in the DOM and
then throws exceptions if you attempt to assign to those properties.
The assignment throws an exception. Which becomes a problem if you
attempt to add a property to the global object and accidentally use a
name that corresponds with the ID of a DOM element (which is quite a
common action). Declaring the variables that are intended to be global
avoids the issue.
But with a correct/"bug-free" implementation I should be able
to use the global.property and var syntaxes interchangibly,
right?

No that is not what I said.
That's another aspect of this bug that puzzles me; all global
code in the first block should "run to completion" before the
second block is entered.

It is inherently confusing to refer to these as blocks. The global
code in the first SCRIPT element should have run to completion before
the start of any processing for the second (in the absence of the
DEFER attribute). Though that is just historical practice and there is
no specification that mandates that behaivure.
Specifically, both variable instantiation and actual code
execution in the first block should come before variable
instantiation of the second block. But parts of this bug
makes me think that IE runs some part of the variable
instantiation in the second block before code execution in
the first block as it comes to the resolution that
the variable needs to be initialized.

I don't follow that. I see nothing to suggest that the first script
element's code has not been fully processed before the second starts.
This is contradicted though by testing to merge the two
script blocks; the bug doesn't show itself in this case.


The scenario is more complex than outlined as I just
provided the simplest possible code to describe the bug.
Specifically, it's about nested variables x.y.z (hindering
the use of var declarations) and the inclusion of separate
script files (therefore the two script blocks). But with
knowledge of the bug's anatomy it will be possible to work
around it.

That is too intangible to be commented upon.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,147
Latest member
CarenSchni
Top