By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,749 Members | 1,627 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,749 IT Pros & Developers. It's quick & easy.

document.getElementById fails when assigning return value to variable with same name as id?

P: n/a
I've got a piece of code where, for all the world, it looks like this
fails in IE 6:

hometab = document.getElementById('hometab');

but this succeeds:

hometabemt = document.getElementById('hometab');

Has anyone ever seen anything like this before, or am I dreaming?

(Both appear to work in firefox.)

Dec 29 '05 #1
Share this Question
Share on Google+
20 Replies


P: n/a
weston wrote:
I've got a piece of code where, for all the world, it looks like this
fails in IE 6:
hometab = document.getElementById('hometab');


What do you mean it 'looks like this fails'?

Vague problem descriptions usually get vague responses :)

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Dec 29 '05 #2

P: n/a
Matt Kruse wrote:
What do you mean it 'looks like this fails'?
Vague problem descriptions usually get vague responses :)


On the contrary, that was a very specific request for clarification. :)
(And quite kind of you.)

I mean that the line:

hometab = document.getElementById('hometab');

where the variable identifier is the same as the id given in the
document, apparently causes IE 6 to cease execution, and claim "Error:
Object doesn't support this property or method. Code: 0."

Meanwhile, the same line, with the identifier slightly changed:

hometabemt = document.getElementById('hometab');

seems to work as expected.

You can examine the context for this observation at:
http://client.logoworks.com/ServiceTraction/

OR... you can try it on Jesse Ruderman's Javascript Shell. There's a
div on that page with id="output". So, visit using IE 6, and try
entering:

output = document.getElementById('output')

It's fun. :)

Then try:

outputemt = document.getElementById('output')

Dec 29 '05 #3

P: n/a
weston wrote:
I mean that the line:
hometab = document.getElementById('hometab');
where the variable identifier is the same as the id given in the
document, apparently causes IE 6 to cease execution, and claim "Error:
Object doesn't support this property or method. Code: 0."


Ah, yes. In IE, objects with an ID cause that ID to become a global variable
referring to the object. One of the bad "shortcuts" that MS put into IE.

Global variables are usually to be avoided anyway. Use the 'var' keyword
inside a function to avoid the global reference and it works fine.
For example,

<html>
<head>
<title></title>
<script>
window.onload = function() {
var x = document.getElementById('x');
alert(x);
}
</script>
</head>
<body>

<div id="x"></div>

</body>
</html>

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Dec 29 '05 #4

P: n/a
On 2005-12-29, weston <no***********************************@canncentral .org> wrote:
Matt Kruse wrote:
What do you mean it 'looks like this fails'?
Vague problem descriptions usually get vague responses :)


On the contrary, that was a very specific request for clarification. :)
(And quite kind of you.)

I mean that the line:

hometab = document.getElementById('hometab');

where the variable identifier is the same as the id given in the
document, apparently causes IE 6 to cease execution, and claim "Error:
Object doesn't support this property or method. Code: 0."

Meanwhile, the same line, with the identifier slightly changed:

hometabemt = document.getElementById('hometab');

seems to work as expected.


try this:

var hometab = document.getElementById('hometab');

or do what I did in a different script.

try {hometab=document.getElementById('hometab');}
catch (q){;}

Bye.
Jasen
Dec 29 '05 #5

P: n/a
Matt Kruse wrote:
Ah, yes. In IE, objects with an ID cause that ID to become a global variable
referring to the object. One of the bad "shortcuts" that MS put into IE.


I'm still a bit confused. I do see that properly scoping the variable
as you're talking about fixes the problem. I just can't figure out for
the life of me why it being a global variable would prevent it from
receiving something via the assignment operator. Other global variables
can do that -- right?

Or is there some hidden magic here I"m not aware of...

Dec 30 '05 #6

P: n/a
weston said the following on 12/30/2005 5:11 PM:
Matt Kruse wrote:

Ah, yes. In IE, objects with an ID cause that ID to become a global variable
referring to the object. One of the bad "shortcuts" that MS put into IE.

I'm still a bit confused. I do see that properly scoping the variable
as you're talking about fixes the problem. I just can't figure out for
the life of me why it being a global variable would prevent it from
receiving something via the assignment operator. Other global variables
can do that -- right?

Or is there some hidden magic here I"m not aware of...


The hidden "magic" is that you are not referencing a *variable* when you
do it in IE, you are referencing the object itself.

myObject = document.getElementById('myObject')

In IE, when you do that, myObject is not a variable. It is a reference
to the container with ID of myObject.

--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq & newsgroup weekly
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
Dec 31 '05 #7

P: n/a
VK

weston wrote:
Matt Kruse wrote:
Ah, yes. In IE, objects with an ID cause that ID to become a global variable
referring to the object. One of the bad "shortcuts" that MS put into IE.


I'm still a bit confused. I do see that properly scoping the variable
as you're talking about fixes the problem. I just can't figure out for
the life of me why it being a global variable would prevent it from
receiving something via the assignment operator. Other global variables
can do that -- right?

Or is there some hidden magic here I"m not aware of...


There is no magic - just an incorrect explanation of the behavior.
Element ID's are not becoming global variables: but elements - with
"id" attribute set to something - are becoming named properties of the
global "window" object. And the "window" object is the default object
of the global execution context. You can consider your script code to
be in the form:

with (window) {
// your code
}

where with(window){} block is being applied seemlessly by the JScript
interpreter. So when meeting a literal on the left side of the
expression without the "var" qualifier, interpreter first looks for an
existing local variable with such name; if failed then it looks for a
global variable with such name; if failed then it looks for window
property with such name. If all above failed then new global variable
will be created.

Samples to play with in the next year:

<html>
<head>
<title>IE's scope 1</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/jscript">
var foo = '';

function test(obj) {
foo = obj.innerText;
alert(foo);
}

</script>
</head>

<body>

<div id="foo" onclick="test(this)" style="cursor:hand">bar</div>

</body>
</html>
<html>
<head>
<title>IE's scope 2</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/jscript">
function test(obj) {
alert(foo.innerText);
// same as:
alert(window.foo.innerText);

alert(self); // '[object]'
// same as:
alert(window.self);
}

</script>
</head>

<body>

<div id="foo" onclick="test(this)" style="cursor:hand">bar</div>

</body>
</html>

P.S. One of these "noises" VK does.

P.P.S. Happy New Year!

Dec 31 '05 #8

P: n/a
VK wrote:
There is no magic - just an incorrect explanation of the behavior.
Element ID's are not becoming global variables: but elements - with
"id" attribute set to something - are becoming named properties of the
global "window" object.


Uh, what do you think global variables are? They are properties of the
global object (window). One in the same.

x=5;
window.x=5;

They both do the same thing in a browser context.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Dec 31 '05 #9

P: n/a
VK

Matt Kruse wrote:
VK wrote:
There is no magic - just an incorrect explanation of the behavior.
Element ID's are not becoming global variables: but elements - with
"id" attribute set to something - are becoming named properties of the
global "window" object.


Uh, what do you think global variables are? They are properties of the
global object (window). One in the same.

x=5;
window.x=5;

They both do the same thing in a browser context.


I'm glad that the "noise" I'm making helped you to turn over the chair
you're sitting on ;-) The are not the same - but their visibility
scopes can be overlapped and the mechanics is rather difficult to
express in words - though rather easy to use. Next year problem, I
guess.

Try:

<html>
<head>
<title>IE's scope</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/jscript">
// Comment and uncomment the declaration below.
// Watch how the results will change. For explanation
// remember that the whole script is running in the
// with (window) {...} block with you don't see but which
// is nevertheless here.
var foo = 'bar';

function test(obj) {
alert(foo);
alert(window['foo']);

}

</script>
</head>

<body>

<div id="foo" onclick="test(this)" style="cursor:hand">bar</div>

</body>
</html>

Dec 31 '05 #10

P: n/a
weston wrote:
Matt Kruse wrote:
Ah, yes. In IE, objects with an ID cause that ID to become a global
variable referring to the object. One of the bad "shortcuts" that MS
put into IE.
I'm still a bit confused. I do see that properly scoping the variable
as you're talking about fixes the problem. I just can't figure out for
the life of me why it being a global variable would prevent it from
receiving something via the assignment operator.


I will try to provide an explanation that I think of as the most
likely one. It is still a long shot, so corrections are welcome.

Undeclared variables and global variables become a property of the
Variable Object of the global execution context, that is, the
Global Object:

| 10.1.3 Variable Instantiation
|
| Every execution context has associated with it a variable object.
| Variables and functions declared in the source text are added as
| properties of the variable object. For function code, parameters
| are added as properties of the variable object.
|
| Which object is used as the variable object and what attributes
| are used for the properties depends on the type of code, but the
| remainder of the behaviour is generic. [...]

| 10.2.1 Global Code
| The scope chain is created and initialised to contain the
| global object and no others.
| Variable instantiation is performed using the global object as
| the variable object and using property attributes { DontDelete }.
| The this value is the global object.

(Could someone please point me to where it is specified that undeclared
variables become properties of the Global Object, too, as implementations
do?)

However,

1. the Global Object appears to be the global Window object in the
Internet Explorer (IE) Application Object Model (AOM), which
includes the IE Document Object Model (DOM);

2. as Matt already roughly explained, in the IE AOM, ID'd (and named IIRC)
elements in the markup result in the creation of properties of the
global Window object that store a reference to the element DOM object
that represents the element, where the properties have the ID or name
of the respective element as their name -- in short, e.g.

<element id="foo" ...>

somewhere in the markup results in

// workaround: let _global be a reference to the Global Object
_global.foo = elementReference;

Now, if JScript as used in IE was a conforming implementation of
ECMAScript Edition 3 that implements ECMAScript regarding the simple
assignment operation to the letter, and let us assume from here that
it does, with

hometab = document.getElementById('hometab');

the following would take place:

| 11.13.1 Simple Assignment ( = )
|
| The production AssignmentExpression : LeftHandSideExpression =
| AssignmentExpression is evaluated as follows:
|
| 1. Evaluate LeftHandSideExpression.
| 2. Evaluate AssignmentExpression.
| 3. Call GetValue(Result(2)).
| 4. Call PutValue(Result(1), Result(3)).
| 5. Return Result(3).

where GetValue is defined as

| 8.7.1 GetValue (V)
|
| 1. If Type(V) is not Reference, return V.
| 2. Call GetBase(V).
| 3. If Result(2) is null, throw a ReferenceError exception.
| 4. Call the [[Get]] method of Result(2), passing GetPropertyName(V) for
| the property name.
| 5. Return Result(4).

and PutValue is defined as

| 8.7.2 PutValue (V, W)
|
| 1. If Type(V) is not Reference, throw a ReferenceError exception.
| 2. Call GetBase(V).
| 3. If Result(2) is null, go to step 6.
| 4. Call the [[Put]] method of Result(2), passing GetPropertyName(V) for
| the property name and W for the value.
| 5. Return.
| 6. Call the [[Put]] method for the global object, passing
| GetPropertyName(V) for the property name and W for the value.
| 7. Return.

The error message you get --

| Error: Object doesn't support this property or method. Code: 0.

-- is most certainly not related in retrieving the object reference with
document.getElementById() as you experience no problems with locally
declared variables or assignments to properties where there is no
respective element (object). So let us ignore GetValue here.

PutValue, however, is more interesting. In step 4 of 11.13.1, PutValue
is called where V is assigned _global.foo and W is assigned some value
(here: the reference to the element object you retrieved with
document.getElementById()), roughly speaking. Now,

| 1. If Type(V) is not Reference, throw a ReferenceError exception.

where Type is defined as

| 5.2 Algorithm Conventions
|
| [...] Type(x) is used as shorthand for "the type of x".

Type(V) is Reference, so no ReferenceError exception is thrown.

| 2. Call GetBase(V).

where GetBase is defined as

| 8.7 The Reference Type
| [...]
| GetBase(V). Returns the base object component of the reference V.

Meaning Result(2) would be _global.

| 3. If Result(2) is null, go to step 6.

Result(2) is not null, so we continue with the next step:

| 4. Call the [[Put]] method of Result(2), passing GetPropertyName(V) for
| the property name and W for the value.

Here is where the "magic" comes in. Keep in mind that _global [Result(2)]
is a reference to the Global Object and that we established before that the
Global Object is a Window _host object_ in the IE AOM.

[[Put]] is defined as follows:

| 8.6.2.2 [[Put]] (P, V)
|
| When the [[Put]] method of O is called with property P and value V, the
| following steps are taken:
|
| 1. Call the [[CanPut]] method of O with name P.
| 2. If Result(1) is false, return.
| 3. If O doesn't have a property with name P, go to step 6.
| 4. Set the value of the property to V. The attributes of the property
| are not changed.
| 5. Return.
| 6. Create a property with name P, set its value to V and give it empty
| attributes.
| 7. Return.

and [[CanPut]] as follows:

| 8.6.2.3 [[CanPut]] (P)
|
| The [[CanPut]] method is used only by the [[Put]] method.
| When the [[CanPut]] method of O is called with property P, the following
| steps are taken:
|
| 1. If O doesn't have a property with name P, go to step 4.
| 2. If the property has the ReadOnly attribute, return false.
| 3. Return true.
| 4. If the [[Prototype]] of O is null, return true.
| 5. Call the [[CanPut]] method of [[Prototype]] of O with property name P.
| 6. Return Result(5).

However,

| 8.6.2 Internal Properties and Methods
|
| Internal properties and methods are not part of the language. They are
| defined by this specification purely for expository purposes. An
| implementation of ECMAScript must behave as if it produced and operated
| upon internal properties in the manner described here. For the purposes
| of this document, the names of internal properties are enclosed in double
| square brackets [[ ]]. When an algorithm uses an internal property of an
| object and the object does not implement the indicated internal property,
| a TypeError exception is thrown.
| [...]
| For native objects the [[Get]], [[Put]], [[CanPut]], [[HasProperty]],
^^^^^^^^^^^^^^
| [[Delete]] and [[DefaultValue]] methods behave as described in described
| in sections 8.6.2.1, 8.6.2.2, 8.6.2.3, 8.6.2.4, 8.6.2.5 and 8.6.2.6,
| respectively, [...]. Host objects may implement these methods in any
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| manner unless specified otherwise; for example, one possibility is that
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| [[Get]] and [[Put]] for a particular host object indeed fetch and store
| property values but [[HasProperty]] always generates false.

<Lasse> With host objects, all bets are off. </Lasse>
Or is there some hidden magic here I"m not aware of...


There probably is.
HTH

PointedEars
Dec 31 '05 #11

P: n/a
Thomas 'PointedEars' Lahn wrote:
Now, if JScript as used in IE was a conforming implementation of
ECMAScript Edition 3 that implements ECMAScript regarding the simple
assignment operation to the letter, and let us assume from here that
it does, with

hometab = document.getElementById('hometab');

the following would take place:

[...]
PutValue, however, is more interesting. In step 4 of 11.13.1, PutValue
is called where V is assigned _global.foo and W is assigned some value


To refer correctly to the example used, that would be _global.hometab
instead, but probably you got the idea already.
PointedEars
Dec 31 '05 #12

P: n/a
"VK" <sc**********@yahoo.com> writes:

[global variables same as properties of global object]
I'm glad that the "noise" I'm making helped you to turn over the chair
you're sitting on ;-) The are not the same - but their visibility
scopes can be overlapped and the mechanics is rather difficult to
express in words - though rather easy to use.


I can see how it would be hard. It does act in a, to me, quite
surprising way.

Global variables are created as properties of the global object, and
in a browser the global object is also the window object (and also
available through the global variable/global object property called
"window").

IE allows using names of id's of elements with an id as if they were
variables. However, they seem to be properties of an object that is
checked *before* the global object when resolving variables, not
the global object itself.

These properties seem to have the "ReadOnly" (and the "DontDelete")
property, so they can't be overwritten by assigning to the variable
name.

See this modified example:

<html>
<head>
<title>IE's scope</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function test(obj) {
alert([foo, window.foo]); // [object],[object] - the DOM element object
window.foo = 42;
alert([foo, window.foo]); // [object],42 - so what appears to be a global
// variable isn't. It's not the global property,
// but is found before.
foo = "foo"; // error, unsupported operation.
// Consistent with the variable foo resolving
// to a read-only property on a different
// object than the global object, and one
// that is used before the global object
// for variable resolution.
}
</script>
</head>
<body>
<div id="foo" onclick="test(this)" style="cursor:hand">bar</div>
</body>
</html>
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Dec 31 '05 #13

P: n/a
Thomas 'PointedEars' Lahn wrote:
<snip>
(Could someone please point me to where it is specified that
undeclared variables become properties of the Global Object,
too, as implementations do?)

<snip>

The primary reason that assigning to undeclared variables (unqualified
Identifiers that do not correspond with Identifiers used with the -
var - keyword in a containing scope) results in the creation of a
property of the global object (so effectively a global variable) is the
algorithm for section 10.1.4:-

<quote cite="ECMA 262,3rd Ed;Section 10.1.4">
10.1.4 Scope Chain and Identifier Resolution
....

During execution, the syntactic production PrimaryExpression :
Identifier is evaluated using the following algorithm:

1. Get the next object in the scope chain. If there isn't one, go to
step 5.
2. Call the [[HasProperty]] method of Result(1), passing the
Identifier as the property.
3. If Result(2) is true, return a value of type Reference whose base
object is Result(1) and whose property name is the Identifier.
4. Go to step 1.
5. Return a value of type Reference whose base object is null and
whose property name is the Identifier.

The result of evaluating an identifier is always a value of type
Reference with its member name component equal to the identifier
string.
</quote>

If an Identifier is an undeclared variable no object on the scope chain
will have a property with the corresponding name (including the global
object), the algorithm gets to step 5 and so the result of Identifier
resolution against the scope chain will be a Reference type with a null
Base Object.

Assignment using that Reference type will use PutValue:-
<quote cite="ECMA 262, 3re Ed; Section 8.7.2">
8.7.2 PutValue (V, W)

1. If Type(V) is not Reference, throw a ReferenceError exception.
2. Call GetBase(V).
3. If Result(2) is null, go to step 6.
4. Call the [[Put]] method of Result(2), passing GetPropertyName(V)
for the property name and W for the value.
5. Return.
6. Call the [[Put]] method for the global object, passing
GetPropertyName(V) for the property name and W for the value.
7. Return.
</quote>

Step 3 finds that the Base object is null and goes to step 6 where the
[[Put]] method of the global object is called, using the Identifier that
is the property name in the Reference type as the name for the [[Put]]
call. Which adds the property to the global object with a name that
corresponds to the original Identifier, effectively creating a new
global variable in the process.

Richard.
Dec 31 '05 #14

P: n/a
Lasse Reichstein Nielsen wrote:
IE allows using names of id's of elements with an id as if they were
variables. However, they seem to be properties of an object that is
checked *before* the global object when resolving variables, not
the global object itself.


Excellent observations, Lasse. I hadn't gone into that detail before to
realize that there is a hidden object in the scope chain in IE that comes
before window. Seems rather absurd and broken to me, and underscores the
importance of depending on global variables as little as possible.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Dec 31 '05 #15

P: n/a
Richard Cornford wrote:
Thomas 'PointedEars' Lahn wrote:
<snip>
(Could someone please point me to where it is specified that
undeclared variables become properties of the Global Object,
too, as implementations do?)

<snip>

The primary reason that assigning to undeclared variables (unqualified
Identifiers that do not correspond with Identifiers used with the -
var - keyword in a containing scope) results in the creation of a
property of the global object (so effectively a global variable) is the
algorithm for section 10.1.4:- [...]


Thank you, reads perfectly reasonable to me :)
\V/ Live long and prosper

PointedEars
Dec 31 '05 #16

P: n/a
Lasse Reichstein Nielsen wrote:
IE allows using names of id's of elements with an id as if they were
variables. However, they seem to be properties of an object that is
checked *before* the global object when resolving variables, not
the global object itself.

These properties seem to have the "ReadOnly" (and the "DontDelete")
property, so they can't be overwritten by assigning to the variable
name.


While it reads more reasonable to me that there is another object
in the scope chain before the Global Object than my assumption
that the Global Object is a host object itself, I do not think
your ReadOnly/DontDelete _attributes_ assumption applies.

It is more likely that this object in the scope chain before the
Global/window object is in fact a host object and therefore, the
algorithms of [[Put]] and [[CanPut]] do not apply. If it instead
followed ES3 to the letter in those, as you indicate by referring
to the "ReadOnly" and "DontDelete" terms, JScript should not error
here.

| 8.6.2.2 [[Put]] (P, V)
|
| When the [[Put]] method of O is called with property P and value V, the
| following steps are taken:
|
| 1. Call the [[CanPut]] method of O with name P.
| 2. If Result(1) is false, return.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| 3. If O doesn't have a property with name P, go to step 6.
| 4. Set the value of the property to V. The attributes of the property
| are not changed.
| 5. Return.
| 6. Create a property with name P, set its value to V and give it empty
| attributes.
| 7. Return.

| 8.6.2.3 [[CanPut]] (P)
|
| The [[CanPut]] method is used only by the [[Put]] method.
| When the [[CanPut]] method of O is called with property P, the following
| steps are taken:
|
| 1. If O doesn't have a property with name P, go to step 4.
| 2. If the property has the ReadOnly attribute, return false.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^
| 3. Return true.
| 4. If the [[Prototype]] of O is null, return true.
| 5. Call the [[CanPut]] method of [[Prototype]] of O with property name P.
| 6. Return Result(5).
PointedEars
Dec 31 '05 #17

P: n/a
VK

Richard Cornford wrote:
The primary reason that assigning to undeclared variables (unqualified
Identifiers that do not correspond with Identifiers used with the -
var - keyword in a containing scope) results in the creation of a
property of the global object (so effectively a global variable) is the
algorithm for section 10.1.4:-


Nothing is *assigned* in case of <div id=something... unless we shall
consider a hardcoded attribute of a HTML element as an assignment in
the script programming sense. The posed broblem is in the twilight zone
above ECMA (pure script context) and below W3C (pure DOM) - and shall
not be your power with you behind this door! :-)
I have a choice now to make a scopes' analysis in IE or get another
Black Label. I'm choosing the latter in the context of tha approaching
New Year - but I'll be back in January.

Dec 31 '05 #18

P: n/a
Lasse Reichstein Nielsen wrote:
<snip>
IE allows using names of id's of elements with an id as if
they were variables. However, they seem to be properties of
an object that is checked *before* the global object when
resolving variables, not the global object itself.

<snip>

The additional object in the scope chain is an interesting theory (and
consistent with the best explanation of some other odd IE behaviour) but
I don't think it holds water because explicitly declaring - foo - as a
global variable significantly changes IE's behaviour:-

<html>
<head>
<title>IE's scope</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">

var foo; //<-- Addition

function test(obj) {
alert(foo+' '+window.foo); // undefined, undefined
window.foo = 42;
alert([foo, window.foo]); // 42,42
foo = "foo"; // No error
}
</script>
</head>
<body>
<div id="foo" onclick="test(this)" style="cursor:hand">bar</div>
</body>
</html>

If there was an extra object on the scope chain with a property named
'foo' that referred to the DOM element the unqualified identifier -
foo - would still be resolved as a property of that object regardless of
the existence of a property of the global object with the name 'foo',
and the declaring of the global variable would not alter IE's output
from your test function.

It is probably worth noting that the commonly recommended 'best
practice' of always explicitly declaring global variables, if followed,
would have eliminated the OP's issue entirely.

Richard.
Dec 31 '05 #19

P: n/a
VK wrote:
Richard Cornford wrote:
The primary reason that assigning to undeclared variables
(unqualified Identifiers that do not correspond with Identifiers
used with the - var - keyword in a containing scope) results in the
creation of a property of the global object (so effectively a global
variable) is the algorithm for section 10.1.4:-


Nothing is *assigned* in case of <div id=something... unless we shall
consider a hardcoded attribute of a HTML element as an assignment in
the script programming sense. The posed broblem is in the twilight
zone above ECMA (pure script context) and below W3C (pure DOM) - and
shall not be your power with you behind this door! :-)
I have a choice now to make a scopes' analysis in IE or get another
Black Label. I'm choosing the latter in the context of tha approaching
New Year - but I'll be back in January.


If you are too drunk to say anything relevant/meaningful/useful it would
be better if you would say nothing at all.

Richard.
Dec 31 '05 #20

P: n/a
VK

Lasse Reichstein Nielsen wrote:
I can see how it would be hard. It does act in a, to me, quite
surprising way.

Global variables are created as properties of the global object, and
in a browser the global object is also the window object (and also
available through the global variable/global object property called
"window").

IE allows using names of id's of elements with an id as if they were
variables. However, they seem to be properties of an object that is
checked *before* the global object when resolving variables, not
the global object itself.

These properties seem to have the "ReadOnly" (and the "DontDelete")
property, so they can't be overwritten by assigning to the variable
name.

See this modified example:

<html>
<head>
<title>IE's scope</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<script type="text/javascript">
function test(obj) {
alert([foo, window.foo]); // [object],[object] - the DOM element object
window.foo = 42;
alert([foo, window.foo]); // [object],42 - so what appears to be a global
// variable isn't. It's not the global property,
// but is found before.
foo = "foo"; // error, unsupported operation.
// Consistent with the variable foo resolving
// to a read-only property on a different
// object than the global object, and one
// that is used before the global object
// for variable resolution.
}
</script>
</head>
<body>
<div id="foo" onclick="test(this)" style="cursor:hand">bar</div>
</body>
</html>


An excellent description!

Just a few comments:

1) DTD is missing
- just joking :-))

2) You've tried (and succeeded with it) to find too much of
structurological sense in something that never had such. That was just
one of sloppy-joe thinkings to "facilitate" the programming to the end
users. Simply in the scope search chain has been added a new step:
Instead of ECMA's
search for local > search for global > create global
IE has:
search for local > search for global > query document.all > create
global

But yes on the abstract model level it is possible to describe this as
a new host object exposing read-only references to DOM objects with
id's. This is still difficult to squeeze into some ECMA definitions as
we serve to this object unprefixed *literals* but they are
automatically treated as *string property names*. I do not recall any
object with such mechanics. So before then this imaginary object itself
should be described in some programming terms.

<my deductive speculation>
Indirectly the whole mess is caused by W3C and their ugly-long and
case-jamping call to the DOM topmost used method:
document.getElementById. It is indeed boring as JavaScript/JScript
sources are still mostly handtyped. So when making the pseudo-DOM
wrapper over "document.all" IE team also decided to use the discussed
*shortcut*. Mainly it's the same thinking as $(id) function from
prototype.js, but IE team went way far too far with the facilitation
process.
P.S. And yes, document.getElementById is just a wrapper over generic
document.all. Another of my noises you may check.
</ my deductive speculation>

3) An unforeseen consequention of this "facilitation" is that IE-users
are being penalizing for bad programming style. Indeed this "scope
conflict" is only possible if one doesn't follow the rule: "every time
you create a new variable you have to use the var qualifier". While you
can avoid name conflicts on your own page, you cannot make any
predictions for element names on pages using your js library. Therefore
Microsoft namely enforced on script developers to work in a "mode
strict" equivalent. I bet they did not mean that but shouldn't we
welcome that? :-)

4) There is still one code section where even accurate programmers
allow themselves to relax sometimes. These are loop cycles:

var ok;
var ok_too;
// but:
for (i=0; i<x; i++) {
}

In case of <div id="i"... on the page the above code will give you
"Object doesn't support this property or method" and you'll die first
before you guess that a hell is going on.

Therefore any variable *including loop counters* must be first
introduced with var qualifier:
for (var i=0; i<x; i++) {
}

Jan 1 '06 #21

This discussion thread is closed

Replies have been disabled for this discussion.