Object-arrays - duplicate object-references

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

    Object-arrays - duplicate object-references

    Hi, I've stumbled into a problem I just can't figure out. I found out
    that variables in JS don't have local scope inside brackets in say, a
    loop, but things still doesn't add up. Also, the phenomena seemed very
    much alike to a closure-related one, but I'm not returning any
    functions as far as I can see (I'm fresh when it comes to closures
    tho). Let me illustrate the very basic task at hand, which is filling
    an array with new objects. All seven positions in the array returned
    point to the same object!

    ---code---

    var o = new Array();

    for(var j=0; j<7; j++) {

    //Create object
    var obj = new SomeType();

    //Manipulate object
    obj.doSomething ();


    o[j] = obj;

    }

    //Array not what is expected here

    someOtherObj.se tArray(o);

    ---/code---


    I also tried the code below to no avail. I don't see how it's any
    different.


    ---code---

    var o = new Array();

    for(var j=0; j<7; j++) {

    //Create object
    o[j] = new SomeType();

    //Manipulate object
    o[j].doSomething();

    }

    //Array not what is expected here

    someOtherObj.se tArray(o);

    ---/code---

    Does anyone have any enlightening explanations for why this occurs,
    and what a solution might be?

    Thanks
  • Thomas 'PointedEars' Lahn

    #2
    Re: Object-arrays - duplicate object-references

    Are Nybakk wrote:
    [...] Let me illustrate the very basic task at hand, which is filling
    an array with new objects. All seven positions in the array returned
    point to the same object!
    No, they don't.
    ---code---
    function SomeType(bar)
    {
    this.foo = bar;
    }

    SomeType.protot ype = {
    constructor: SomeType,
    doSomething: function() {}
    };
    var o = new Array();
    >
    for(var j=0; j<7; j++) {
    >
    //Create object
    var obj = new SomeType();
    For proof, replace with this line with

    var obj = new SomeType(j);
    //Manipulate object
    obj.doSomething ();
    >
    >
    o[j] = obj;
    >
    }
    >
    //Array not what is expected here
    You have not said what you expect. Anyhow:

    // 0,1
    window.alert([o[0].foo, o[1].foo]);
    someOtherObj.se tArray(o);
    The error may lie in here.
    Does anyone have any enlightening explanations for why this occurs,
    and what a solution might be?
    Maybe if you posted the code of SomeType() or someOtherObj.se tArray().




    PointedEars
    --
    Prototype.js was written by people who don't know javascript for people
    who don't know javascript. People who don't know javascript are not
    the best source of advice on designing systems that use javascript.
    -- Richard Cornford, cljs, <f806at$ail$1$8 300dec7@news.de mon.co.uk>

    Comment

    • Are Nybakk

      #3
      Re: Object-arrays - duplicate object-references

      On Apr 12, 11:31 am, Thomas 'PointedEars' Lahn <PointedE...@we b.de>
      wrote:
      Are Nybakk wrote:
      [...] Let me illustrate the very basic task at hand, which is filling
      an array with new objects. All seven positions in the array returned
      point to the same object!
      >
      No, they don't.
      If so, they are all identical objects, which is not the case. The
      objects are created correctly, I have confirmed it.

      *snip*
      //Array not what is expected here
      >
      You have not said what you expect. Anyhow:
      An array of 7 different objects?
      >
      // 0,1
      window.alert([o[0].foo, o[1].foo]);
      >
      someOtherObj.se tArray(o);
      >
      The error may lie in here.
      This was just to illustrate what it's beeing used for later. The array
      is wrong before this call.
      >
      Does anyone have any enlightening explanations for why this occurs,
      and what a solution might be?
      >
      Maybe if you posted the code of SomeType() or someOtherObj.se tArray().
      Simplified:

      function SomeType() {

      //private variables
      var m_id = 0;

      SomeType.protot ype.setId = function(id) {
      m_id = id;
      }

      SomeType.protot ype.getId = function() {
      return m_id;
      }

      }

      Is it correct to set the methods inside the class like this btw? I
      tested it and creating objects worked. Is it possible that all objects
      of this type somehow operate on the same "private" variables?

      *snip*

      Comment

      • Are Nybakk

        #4
        Re: Object-arrays - duplicate object-references

        *snip*
        Maybe if you posted the code of SomeType() or someOtherObj.se tArray().
        >
        Simplified:
        >
        function SomeType() {
        >
        //private variables
        var m_id = 0;
        >
        SomeType.protot ype.setId = function(id) {
        m_id = id;
        }
        >
        SomeType.protot ype.getId = function() {
        return m_id;
        }
        >
        }
        >
        Is it correct to set the methods inside the class like this btw? I
        tested it and creating objects worked. Is it possible that all objects
        of this type somehow operate on the same "private" variables?
        I think I was into something here. It seems the code below works as it
        was meant to be :)

        function SomeType() {

        //private variables
        var m_id = 0;

        }

        SomeType.protot ype.setId = function(id) {
        this.m_id = id;
        }

        SomeType.protot ype.getId = function() {
        return this.m_id;
        }

        Comment

        • Thomas 'PointedEars' Lahn

          #5
          Re: Object-arrays - duplicate object-references

          Are Nybakk wrote:
          [...] Thomas 'PointedEars' Lahn [...] wrote:
          >Are Nybakk wrote:
          >>[...] Let me illustrate the very basic task at hand, which is filling
          >>an array with new objects. All seven positions in the array returned
          >>point to the same object!
          >No, they don't.
          >
          If so, they are all identical objects,
          Pardon? You have said that they point to (refer to) the same object, my
          test case shows that they do not. If what I said (and what my test case
          proves) is true, there are different objects, of course.
          which is not the case.
          Of course not.
          The objects are created correctly, I have confirmed it.
          Doesn't matter.
          *snip*
          >
          >>//Array not what is expected here
          >You have not said what you expect. Anyhow:
          >
          An array of 7 different objects?
          Which is what happens. Have you even bothered to run my test case?
          > // 0,1
          > window.alert([o[0].foo, o[1].foo]);
          >>
          >>someOtherObj. setArray(o);
          >The error may lie in here.
          >
          This was just to illustrate what it's beeing used for later. The array
          is wrong before this call.
          Then the error may lie only in the constructor, obj.doSomething (), or the
          way you instantiate your variables.
          >>Does anyone have any enlightening explanations for why this occurs,
          >>and what a solution might be?
          >Maybe if you posted the code of SomeType() or someOtherObj.se tArray().
          >
          Simplified:
          >
          function SomeType() {
          >
          //private variables
          var m_id = 0;
          >
          SomeType.protot ype.setId = function(id) {
          m_id = id;
          }
          >
          SomeType.protot ype.getId = function() {
          return m_id;
          }
          }
          >
          Is it correct to set the methods inside the class like this btw?
          Firstly, there are no classes, these are languages that provide
          prototype-based inheritance:




          It is correct, however less efficient than one-time redefinition/
          augmentation, to try augmenting/redefining the prototype object in the
          constructor.
          I tested it and creating objects worked. Is it possible that all objects
          of this type somehow operate on the same "private" variables?
          Nevertheless, with such an initialization you do create a closure, with
          `m_id' being a variable bound to the local execution context of the
          constructor, and so the methods do operate on the same local variable
          instantiated on the last constructor call (since that is when you define
          the prototype methods last).

          Here is a way to create private members that works as supposed:

          function SomeType()
          {
          // private member
          var m_id = 0;

          this.setId = function(id) {
          m_id = id;
          };

          this.getId = function() {
          return m_id;
          };
          }

          As you can see, in current client-side ECMAScript implementations you can
          only buy information hiding with decreased memory efficiency.




          HTH

          PointedEars
          --
          realism: HTML 4.01 Strict
          evangelism: XHTML 1.0 Strict
          madness: XHTML 1.1 as application/xhtml+xml
          -- Bjoern Hoehrmann

          Comment

          • Thomas 'PointedEars' Lahn

            #6
            Re: Object-arrays - duplicate object-references

            Are Nybakk wrote:
            *snip*
            >>Maybe if you posted the code of SomeType() or someOtherObj.se tArray().
            >Simplified:
            >>
            >function SomeType() {
            > //private variables
            > var m_id = 0;
            >>
            > SomeType.protot ype.setId = function(id) {
            > m_id = id;
            > }
            >>
            > SomeType.protot ype.getId = function() {
            > return m_id;
            > }
            >}
            >>
            >Is it correct to set the methods inside the class like this btw? I
            >tested it and creating objects worked. Is it possible that all objects
            >of this type somehow operate on the same "private" variables?
            >
            I think I was into something here. It seems the code below works as it
            was meant to be :)
            Only that you have no information hiding anymore, and that the local
            variable really has become superfluous as it is _not_ used:
            function SomeType() {
            >
            //private variables
            var m_id = 0;
            Unused local variable.
            }
            >
            SomeType.protot ype.setId = function(id) {
            this.m_id = id;
            Creates a new property of the calling object named `m_id', value of `id', or
            overwrites the value of the existing property with that name.
            }
            >
            SomeType.protot ype.getId = function() {
            return this.m_id;
            Returns the value of the property named `m_id' of the calling object, or
            `undefined' if the property has not been defined or set to `undefined' before.
            }
            And so

            var o = new SomeType();
            o.m_id = 'x';
            window.alert(o. m_id);

            is possible again. Not quite what you wanted, is it?


            PointedEars
            --
            Use any version of Microsoft Frontpage to create your site.
            (This won't prevent people from viewing your source, but no one
            will want to steal it.)
            -- from <http://www.vortex-webdesign.com/help/hidesource.htm>

            Comment

            • Thomas 'PointedEars' Lahn

              #7
              Re: Object-arrays - duplicate object-references

              Thomas 'PointedEars' Lahn wrote:
              Are Nybakk wrote:
              >SomeType.proto type.getId = function() {
              > return this.m_id;
              >
              Returns the value of the property named `m_id' of the calling object, or
              `undefined' if the property has not been defined or set to `undefined' before.
              >
              >}
              >
              And so
              >
              var o = new SomeType();
              o.m_id = 'x';
              window.alert(o. m_id);
              >
              is possible again. Not quite what you wanted, is it?
              For a better proof that nothing is private anymore then, use

              var o = new SomeType();
              o.m_id = 'x';
              window.alert(o. getId());

              or

              var o = new SomeType();
              o.setId('x');
              window.alert(o. m_id);


              PointedEars
              --
              realism: HTML 4.01 Strict
              evangelism: XHTML 1.0 Strict
              madness: XHTML 1.1 as application/xhtml+xml
              -- Bjoern Hoehrmann

              Comment

              • Are Nybakk

                #8
                Re: Object-arrays - duplicate object-references

                *snip*
                Maybe if you posted the code of SomeType() or someOtherObj.se tArray().
                >
                Simplified:
                >
                function SomeType() {
                >
                //private variables
                var m_id = 0;
                >
                SomeType.protot ype.setId = function(id) {
                m_id = id;
                }
                >
                SomeType.protot ype.getId = function() {
                return m_id;
                }
                >
                }
                >
                Is it correct to set the methods inside the class like this btw? I
                tested it and creating objects worked. Is it possible that all objects
                of this type somehow operate on the same "private" variables?
                I think I was into something here. It seems the code below works as it
                was meant to be :)

                function SomeType() {

                //private variables
                var m_id = 0;

                }

                SomeType.protot ype.setId = function(id) {
                this.m_id = id;
                }

                SomeType.protot ype.getId = function() {
                return this.m_id;
                }

                Comment

                • Are Nybakk

                  #9
                  Re: Object-arrays - duplicate object-references

                  On Apr 12, 12:48 pm, Thomas 'PointedEars' Lahn <PointedE...@we b.de>
                  wrote:
                  Thomas 'PointedEars' Lahn wrote:
                  Are Nybakk wrote:
                  SomeType.protot ype.getId = function() {
                  return this.m_id;
                  >
                  Returns the value of the property named `m_id' of the calling object, or
                  `undefined' if the property has not been defined or set to `undefined' before.
                  Yes, I bumped into this as I had set properties on some of those
                  variables in the constructor. The methods did then not know of it,
                  giving 'undefined' results.
                  >
                  }
                  >
                  And so
                  >
                  var o = new SomeType();
                  o.m_id = 'x';
                  window.alert(o. m_id);
                  >
                  is possible again. Not quite what you wanted, is it?
                  >
                  For a better proof that nothing is private anymore then, use
                  >
                  var o = new SomeType();
                  o.m_id = 'x';
                  window.alert(o. getId());
                  >
                  or
                  >
                  var o = new SomeType();
                  o.setId('x');
                  window.alert(o. m_id);
                  I think I'm beginning to hate JS :p Thanks for clearing this up.

                  I wonder which is generally the better of two evils.. inefficient data-
                  hiding or efficient public data... any thoughts? Some of my classes
                  contain only "static" methods, so there's no problem there, but I have
                  some others which contains data, like in this example, and just 1-2
                  methods. I wouldn't say the data-hiding is _necessary_, but in some
                  cases value-checking might be nice to have. The code certainly would
                  be more robust and reusable that way. I guess I'm pretty much
                  answering my own question.
                  >
                  PointedEars
                  --
                  realism: HTML 4.01 Strict
                  evangelism: XHTML 1.0 Strict
                  madness: XHTML 1.1 as application/xhtml+xml
                  -- Bjoern Hoehrmann

                  Comment

                  • Thomas 'PointedEars' Lahn

                    #10
                    Re: Object-arrays - duplicate object-references

                    Are Nybakk wrote:
                    [...] Thomas 'PointedEars' Lahn [...] wrote:
                    >For a better proof that nothing is private anymore then, use
                    >>
                    > var o = new SomeType();
                    > o.m_id = 'x';
                    > window.alert(o. getId());
                    >>
                    >or
                    >>
                    > var o = new SomeType();
                    > o.setId('x');
                    > window.alert(o. m_id);
                    >
                    I think I'm beginning to hate JS :p Thanks for clearing this up.
                    >
                    I wonder which is generally the better of two evils.. inefficient data-
                    hiding or efficient public data... any thoughts? Some of my classes
                    contain only "static" methods, so there's no problem there, but I have
                    some others which contains data, like in this example, and just 1-2
                    methods. I wouldn't say the data-hiding is _necessary_, but in some
                    cases value-checking might be nice to have. The code certainly would
                    be more robust and reusable that way. I guess I'm pretty much
                    answering my own question.
                    Yes, why not use the best of both worlds? It appears to reasonable to use
                    private members and protected accessor methods only when information hiding
                    or value checking is required, and public properties otherwise.

                    However, to ease your pain a little bit ;-) there are ECMAScript
                    implementations that support getters and setters. For example,
                    JavaScript 1.5:

                    function SomeType()
                    {
                    var id = 0;

                    this.__defineGe tter__(
                    "id",
                    function() {
                    return id;
                    }
                    );

                    this.__defineSe tter__(
                    "id",
                    function(v) {
                    if (!isNaN(v)) id = v;
                    }
                    );
                    }

                    var o = new SomeType();

                    o.id = "a";

                    // 0
                    window.alert(o. id);


                    Please trim your quotes to the necessary minimum.


                    PointedEars
                    --
                    realism: HTML 4.01 Strict
                    evangelism: XHTML 1.0 Strict
                    madness: XHTML 1.1 as application/xhtml+xml
                    -- Bjoern Hoehrmann

                    Comment

                    • Lasse Reichstein Nielsen

                      #11
                      Re: Object-arrays - duplicate object-references

                      Are Nybakk <news@arenybakk .comwrites:
                      I think I was into something here. It seems the code below works as it
                      was meant to be :)
                      Almost.
                      function SomeType() {
                      >
                      //private variables
                      var m_id = 0;
                      This declares a local variable that is not accessible by any other
                      code. You can remove the declaration and not change anything.

                      You might vant to do:
                      this.m_id = 0;
                      instead, which does initialize the object property that the following
                      methods access:
                      SomeType.protot ype.setId = function(id) {
                      this.m_id = id;
                      }
                      /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

                      • Are Nybakk

                        #12
                        Re: Object-arrays - duplicate object-references

                        *snip*
                        However, to ease your pain a little bit ;-) there are ECMAScript
                        implementations that support getters and setters. For example,
                        JavaScript 1.5:
                        >
                        *snip*

                        Ah, now that's very nice! Too bad it seems IE doesn't support this.
                        Personally I don't see any point at all in using IE, but the users do,
                        sadly. Thanks again for the input, it was really useful 8)

                        (Sigh, I need to go back to a real usenet-client. Damn Google...)

                        Comment

                        Working...