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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • weston

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

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

    hometab = document.getEle mentById('homet ab');

    but this succeeds:

    hometabemt = document.getEle mentById('homet ab');

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

    (Both appear to work in firefox.)

  • Matt Kruse

    #2
    Re: document.getEle mentById fails when assigning return value to variable with same name as id?

    weston wrote:[color=blue]
    > I've got a piece of code where, for all the world, it looks like this
    > fails in IE 6:
    > hometab = document.getEle mentById('homet ab');[/color]

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

    Vague problem descriptions usually get vague responses :)

    --
    Matt Kruse




    Comment

    • weston

      #3
      Re: document.getEle mentById fails when assigning return value to variable with same name as id?

      Matt Kruse wrote:
      [color=blue]
      > What do you mean it 'looks like this fails'?
      > Vague problem descriptions usually get vague responses :)[/color]

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

      I mean that the line:

      hometab = document.getEle mentById('homet ab');

      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.getEle mentById('homet ab');

      seems to work as expected.

      You can examine the context for this observation at:


      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.getEle mentById('outpu t')

      It's fun. :)

      Then try:

      outputemt = document.getEle mentById('outpu t')

      Comment

      • Matt Kruse

        #4
        Re: document.getEle mentById fails when assigning return value to variable with same name as id?

        weston wrote:[color=blue]
        > I mean that the line:
        > hometab = document.getEle mentById('homet ab');
        > 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."[/color]

        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.getEle mentById('x');
        alert(x);
        }
        </script>
        </head>
        <body>

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

        </body>
        </html>

        --
        Matt Kruse




        Comment

        • Jasen Betts

          #5
          Re: document.getEle mentById fails when assigning return value to variable with same name as id?

          On 2005-12-29, weston <notsew-reversePreceedi ngAndRemoveThis @canncentral.or g> wrote:[color=blue]
          > Matt Kruse wrote:
          >[color=green]
          >> What do you mean it 'looks like this fails'?
          >> Vague problem descriptions usually get vague responses :)[/color]
          >
          > On the contrary, that was a very specific request for clarification. :)
          > (And quite kind of you.)
          >
          > I mean that the line:
          >
          > hometab = document.getEle mentById('homet ab');
          >
          > 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.getEle mentById('homet ab');
          >
          > seems to work as expected.
          >[/color]

          try this:

          var hometab = document.getEle mentById('homet ab');

          or do what I did in a different script.

          try {hometab=docume nt.getElementBy Id('hometab');}
          catch (q){;}



          Bye.
          Jasen

          Comment

          • weston

            #6
            Re: document.getEle mentById fails when assigning return value to variable with same name as id?

            Matt Kruse wrote:
            [color=blue]
            > 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.[/color]

            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...

            Comment

            • Randy Webb

              #7
              Re: document.getEle mentById fails when assigning return value tovariable with same name as id?

              weston said the following on 12/30/2005 5:11 PM:[color=blue]
              > Matt Kruse wrote:
              >
              >[color=green]
              >>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.[/color]
              >
              >
              > 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...[/color]

              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.getEle mentById('myObj ect')

              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.javas cript FAQ - http://jibbering.com/faq & newsgroup weekly
              Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

              Comment

              • VK

                #8
                Re: document.getEle mentById fails when assigning return value to variable with same name as id?


                weston wrote:[color=blue]
                > Matt Kruse wrote:
                >[color=green]
                > > 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.[/color]
                >
                > 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...[/color]

                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(t his)" style="cursor:h and">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.inner Text);
                // same as:
                alert(window.fo o.innerText);

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

                </script>
                </head>

                <body>

                <div id="foo" onclick="test(t his)" style="cursor:h and">bar</div>

                </body>
                </html>

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

                P.P.S. Happy New Year!

                Comment

                • Matt Kruse

                  #9
                  Re: document.getEle mentById fails when assigning return value to variable with same name as id?

                  VK wrote:[color=blue]
                  > 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.[/color]

                  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




                  Comment

                  • VK

                    #10
                    Re: document.getEle mentById fails when assigning return value to variable with same name as id?


                    Matt Kruse wrote:[color=blue]
                    > VK wrote:[color=green]
                    > > 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.[/color]
                    >
                    > 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.[/color]

                    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(t his)" style="cursor:h and">bar</div>

                    </body>
                    </html>

                    Comment

                    • Thomas 'PointedEars' Lahn

                      #11
                      Re: document.getEle mentById fails when assigning return value to variable with same name as id?

                      weston wrote:
                      [color=blue]
                      > Matt Kruse wrote:[color=green]
                      >> 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.[/color]
                      >
                      > 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.[/color]

                      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 = elementReferenc e;

                      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.getEle mentById('homet ab');

                      the following would take place:

                      | 11.13.1 Simple Assignment ( = )
                      |
                      | The production AssignmentExpre ssion : LeftHandSideExp ression =
                      | AssignmentExpre ssion is evaluated as follows:
                      |
                      | 1. Evaluate LeftHandSideExp ression.
                      | 2. Evaluate AssignmentExpre ssion.
                      | 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.getEle mentById() 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.getEle mentById()), 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>
                      [color=blue]
                      > Or is there some hidden magic here I"m not aware of...[/color]

                      There probably is.


                      HTH

                      PointedEars

                      Comment

                      • Thomas 'PointedEars' Lahn

                        #12
                        Re: document.getEle mentById fails when assigning return value to variable with same name as id?

                        Thomas 'PointedEars' Lahn wrote:
                        [color=blue]
                        > 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.getEle mentById('homet ab');
                        >
                        > 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[/color]

                        To refer correctly to the example used, that would be _global.hometab
                        instead, but probably you got the idea already.


                        PointedEars

                        Comment

                        • Lasse Reichstein Nielsen

                          #13
                          Re: document.getEle mentById fails when assigning return value tovariable with same name as id?

                          "VK" <schools_ring@y ahoo.com> writes:

                          [global variables same as properties of global object]
                          [color=blue]
                          > 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.[/color]

                          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(t his)" style="cursor:h and">bar</div>
                          </body>
                          </html>


                          /L
                          --
                          Lasse Reichstein Nielsen - lrn@hotpop.com
                          DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
                          'Faith without judgement merely degrades the spirit divine.'

                          Comment

                          • Richard Cornford

                            #14
                            Re: document.getEle mentById fails when assigning return value to variable with same name as id?

                            Thomas 'PointedEars' Lahn wrote:
                            <snip>[color=blue]
                            > (Could someone please point me to where it is specified that
                            > undeclared variables become properties of the Global Object,
                            > too, as implementations do?)[/color]
                            <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 PrimaryExpressi on :
                            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.


                            Comment

                            • Matt Kruse

                              #15
                              Re: document.getEle mentById fails when assigning return value to variable with same name as id?

                              Lasse Reichstein Nielsen wrote:[color=blue]
                              > 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.[/color]

                              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




                              Comment

                              Working...