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

Discussion in 'Javascript' started by weston, Dec 29, 2005.

  1. weston

    weston Guest

    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.)
    weston, Dec 29, 2005
    #1
    1. Advertising

  2. weston

    Matt Kruse Guest

    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
    Matt Kruse, Dec 29, 2005
    #2
    1. Advertising

  3. weston

    weston Guest

    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')
    weston, Dec 29, 2005
    #3
  4. weston

    Matt Kruse Guest

    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
    Matt Kruse, Dec 29, 2005
    #4
  5. weston

    weston Guest

    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...
    weston, Dec 30, 2005
    #5
  6. weston

    Randy Webb Guest

    Re: document.getElementById fails when assigning return value tovariable with same name as id?

    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/
    Randy Webb, Dec 31, 2005
    #6
  7. weston

    VK Guest

    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!
    VK, Dec 31, 2005
    #7
  8. weston

    Matt Kruse Guest

    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
    Matt Kruse, Dec 31, 2005
    #8
  9. weston

    VK Guest

    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>
    VK, Dec 31, 2005
    #9
  10. 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
    Thomas 'PointedEars' Lahn, Dec 31, 2005
    #10
  11. 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
    Thomas 'PointedEars' Lahn, Dec 31, 2005
    #11
  12. Re: document.getElementById fails when assigning return value tovariable with same name as id?

    "VK" <> 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 -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, Dec 31, 2005
    #12
  13. weston

    Matt Kruse Guest

    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
    Matt Kruse, Dec 31, 2005
    #13
  14. 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.
    Richard Cornford, Dec 31, 2005
    #14
  15. 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
    Thomas 'PointedEars' Lahn, Dec 31, 2005
    #15
  16. 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
    Thomas 'PointedEars' Lahn, Dec 31, 2005
    #16
  17. weston

    VK Guest

    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.
    VK, Dec 31, 2005
    #17
  18. 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.
    Richard Cornford, Dec 31, 2005
    #18
  19. 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.
    Richard Cornford, Dec 31, 2005
    #19
  20. weston

    VK Guest

    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++) {
    }
    VK, Jan 1, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. wk
    Replies:
    5
    Views:
    160
    Dietmar Meier
    Apr 22, 2005
  2. Replies:
    6
    Views:
    235
  3. Martin
    Replies:
    3
    Views:
    135
  4. Replies:
    4
    Views:
    153
    Jonas Raoni
    Nov 21, 2006
  5. ll
    Replies:
    2
    Views:
    323
    GArlington
    Aug 22, 2008
Loading...

Share This Page