Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > document.getElementById fails when assigning return value to variable with same name as id?

Reply
Thread Tools

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

 
 
weston
Guest
Posts: n/a
 
      12-29-2005
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.)

 
Reply With Quote
 
 
 
 
Matt Kruse
Guest
Posts: n/a
 
      12-29-2005
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


 
Reply With Quote
 
 
 
 
weston
Guest
Posts: n/a
 
      12-29-2005
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')

 
Reply With Quote
 
Matt Kruse
Guest
Posts: n/a
 
      12-29-2005
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


 
Reply With Quote
 
weston
Guest
Posts: n/a
 
      12-30-2005
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...

 
Reply With Quote
 
Randy Webb
Guest
Posts: n/a
 
      12-31-2005
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/
 
Reply With Quote
 
VK
Guest
Posts: n/a
 
      12-31-2005

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!

 
Reply With Quote
 
Matt Kruse
Guest
Posts: n/a
 
      12-31-2005
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


 
Reply With Quote
 
VK
Guest
Posts: n/a
 
      12-31-2005

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>

 
Reply With Quote
 
Thomas 'PointedEars' Lahn
Guest
Posts: n/a
 
      12-31-2005
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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is this legal? assigning return value to a const ref? flopbucket C++ 10 10-31-2007 06:11 PM
adding a variable name to a hash to name is part of the variable name Bobby Chamness Perl 2 04-22-2007 09:54 PM
Assigning methods to objects, and assigning onreadystatechange to an XMLHttpRequest -- an inconsistency? weston Javascript 1 09-22-2006 09:33 AM
what value does lack of return or empty "return;" return Greenhorn C Programming 15 03-06-2005 08:19 PM
Can I create an array of tags by assigning same name? Jenny Javascript 1 10-04-2004 07:09 PM



Advertisments