Object-arrays - duplicate object-references

Discussion in 'Javascript' started by Are Nybakk, Apr 12, 2008.

  1. Are Nybakk

    Are Nybakk Guest

    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.setArray(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.setArray(o);

    ---/code---

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

    Thanks
    Are Nybakk, Apr 12, 2008
    #1
    1. Advertising

  2. 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.prototype = {
    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.setArray(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.setArray().

    http://www.jibbering.com/faq/faq_notes/clj_posts.html#ps1DontWork


    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$>
    Thomas 'PointedEars' Lahn, Apr 12, 2008
    #2
    1. Advertising

  3. Are Nybakk

    Are Nybakk Guest

    On Apr 12, 11:31 am, 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, 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.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.

    >
    > > 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.setArray().


    Simplified:

    function SomeType() {

    //private variables
    var m_id = 0;

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

    SomeType.prototype.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*
    Are Nybakk, Apr 12, 2008
    #3
  4. Are Nybakk

    Are Nybakk Guest

    *snip*

    > > Maybe if you posted the code of SomeType() or someOtherObj.setArray().

    >
    > Simplified:
    >
    > function SomeType() {
    >
    > //private variables
    > var m_id = 0;
    >
    > SomeType.prototype.setId = function(id) {
    > m_id = id;
    > }
    >
    > SomeType.prototype.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.prototype.setId = function(id) {
    this.m_id = id;
    }

    SomeType.prototype.getId = function() {
    return this.m_id;
    }
    Are Nybakk, Apr 12, 2008
    #4
  5. 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.setArray().

    >
    > Simplified:
    >
    > function SomeType() {
    >
    > //private variables
    > var m_id = 0;
    >
    > SomeType.prototype.setId = function(id) {
    > m_id = id;
    > }
    >
    > SomeType.prototype.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:

    http://javascript.crockford.com/javascript.html
    http://javascript.crockford.com/inheritance.html

    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.

    http://www.crockford.com/javascript/private.html


    HTH

    PointedEars
    --
    realism: HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness: XHTML 1.1 as application/xhtml+xml
    -- Bjoern Hoehrmann
    Thomas 'PointedEars' Lahn, Apr 12, 2008
    #5
  6. Are Nybakk wrote:
    > *snip*
    >>> Maybe if you posted the code of SomeType() or someOtherObj.setArray().

    >> Simplified:
    >>
    >> function SomeType() {
    >> //private variables
    >> var m_id = 0;
    >>
    >> SomeType.prototype.setId = function(id) {
    >> m_id = id;
    >> }
    >>
    >> SomeType.prototype.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.prototype.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.prototype.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>
    Thomas 'PointedEars' Lahn, Apr 12, 2008
    #6
  7. Thomas 'PointedEars' Lahn wrote:
    > Are Nybakk wrote:
    >> SomeType.prototype.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
    Thomas 'PointedEars' Lahn, Apr 12, 2008
    #7
  8. Are Nybakk

    Are Nybakk Guest

    *snip*

    > > Maybe if you posted the code of SomeType() or someOtherObj.setArray().

    >
    > Simplified:
    >
    > function SomeType() {
    >
    > //private variables
    > var m_id = 0;
    >
    > SomeType.prototype.setId = function(id) {
    > m_id = id;
    > }
    >
    > SomeType.prototype.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.prototype.setId = function(id) {
    this.m_id = id;
    }

    SomeType.prototype.getId = function() {
    return this.m_id;
    }
    Are Nybakk, Apr 12, 2008
    #8
  9. Are Nybakk

    Are Nybakk Guest

    On Apr 12, 12:48 pm, Thomas 'PointedEars' Lahn <>
    wrote:
    > Thomas 'PointedEars' Lahn wrote:
    > > Are Nybakk wrote:
    > >> SomeType.prototype.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
    Are Nybakk, Apr 12, 2008
    #9
  10. 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.__defineGetter__(
    "id",
    function() {
    return id;
    }
    );

    this.__defineSetter__(
    "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
    Thomas 'PointedEars' Lahn, Apr 12, 2008
    #10
  11. Are Nybakk <> writes:

    > 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.prototype.setId = function(id) {
    > this.m_id = id;
    > }


    /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, Apr 12, 2008
    #11
  12. Are Nybakk

    Are Nybakk Guest

    *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...)
    Are Nybakk, Apr 12, 2008
    #12
    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. Roger Leigh
    Replies:
    8
    Views:
    437
    Karl Heinz Buchegger
    Nov 17, 2003
  2. Replies:
    0
    Views:
    468
  3. Philipp
    Replies:
    21
    Views:
    1,127
    Philipp
    Jan 20, 2009
  4. Jack Bates
    Replies:
    3
    Views:
    307
    Steven D'Aprano
    Aug 6, 2011
  5. Ohad Lutzky
    Replies:
    0
    Views:
    109
    Ohad Lutzky
    Oct 14, 2006
Loading...

Share This Page