Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    Regular Coder
    Join Date
    Apr 2005
    Location
    Texas
    Posts
    448
    Thanks
    24
    Thanked 63 Times in 63 Posts

    Unexpected behavior of object

    Ok, so I wanted to use the following object to copy the contents of the Report array at index [file][entry].
    Code:
      Selected = {
       fileIndex : file,
       entryIndex : entry,
       Entry : Report[file][entry]
       }
    This was done so that the user may perform modifications to the entry without updating the entry until I have run validation on the input. Then I used
    Code:
      if(valid)
       Report[Selected.fileIndex][Selected.entryIndex] = Selected.Entry
    to finish up. I noticed that the Report array was getting the new input even when I didn't validate.

    I used the following to view all the contents of the Report Array in real time

    Code:
    window.setInterval('SHOW_ARRAY();',200);
    Report=[];
    function SHOW_ARRAY(){
     HTML('ReportDebug','')	//Reset "ReportDebug" HTML element
     for(var t in Report){
      for(var y in Report[t]){
       for(var u in Report[t][y]){
        HTML('ReportDebug','<span style="position:relative ; border:2px solid black">'+Report[t][y][u]+'</span>',1) // last argument signifies to append HTML element
        }
       }
       HTML('ReportDebug','<br />',1)
      }
     }
    And what I discovered was that whenever I stored values in Selected.Entry the Report array would update with those values!
    This is my first attempt to create an object in this fashion, so my only guess is that Selected.Entry is not independent from Report[file][entry], but instead some kind of pointer... Where have I gone wrong, and how can I accomplish my goal?
    Let me know if my code samples were too brief.

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,947
    Thanks
    79
    Thanked 4,424 Times in 4,389 Posts
    my only guess is that Selected.Entry is not independent from Report[file][entry], but instead some kind of pointer
    Correct. JavaScript does *NOT* copy objects. It only copies *REFERENCES* to the objects. So any change to the thing being REFERENCED is immediately reflected.

    Only primitive values are copied. So if Report[file][entry] doesn't refer to some primitive value, it won't be copied.

    This is the same with most modern languages, by the way, so don't blame JavaScript.

    If you want to get the *VALUE* of an object and store it independently, you would have to clone the object or somehow invoke a function to get a "value" (whatever that might mean in your context), etc.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    blaze4218 (10-05-2011)

  • #3
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,947
    Thanks
    79
    Thanked 4,424 Times in 4,389 Posts
    And clearly Report[][] is not a primitive value, since I see you then use Report[t][y][u] implying that Report[][] will be an array, yes? So you'd need to copy the array. But if any elements of the array are also object references, even that might not be enough.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #4
    Regular Coder
    Join Date
    Apr 2005
    Location
    Texas
    Posts
    448
    Thanks
    24
    Thanked 63 Times in 63 Posts
    Well there is an array at Report[file][entry], so I guess not primitive.
    The innermost array does hold primitive values. Based on your wording I did a quick google search for "clone object javascript" and found the following:

    http://www.thespanner.co.uk/2008/04/...oning-objects/
    Code:
    function clone(o) {
     return eval(uneval(o));
    }
    http://stackoverflow.com/questions/7...-in-javascript
    Code:
    function clone(obj) {
        if (null == obj || "object" != typeof obj) return obj;
        var copy = obj.constructor();
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
        }
        return copy;
    }
    Is that what you are recommending?

  • #5
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,947
    Thanks
    79
    Thanked 4,424 Times in 4,389 Posts
    I dunno if I'm "recommending" it. Just saying that if you need to keep a copy of the original contents you'll have to do something like that.

    You say "The innermost array does hold primitive values" so you really don't need either of those methods...both of which have a lot of over head. You can easily clone an array:
    Code:
    function cloneArray( ar )
    {
        var newar = [];
        for ( var i = 0; i < ar.length; ++i ) newar.push( ar[i] );
    }
    A lot more efficient than either of those.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #6
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,947
    Thanks
    79
    Thanked 4,424 Times in 4,389 Posts
    By the by, you might be interested to know that, of all things, VBScript actually *does* clone arrays when you assign them. Go figure. Of course, whether VBScript qualifies as a "modern language" or not is pretty debatable. <grin/>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #7
    Regular Coder
    Join Date
    Sep 2011
    Location
    Sweden
    Posts
    154
    Thanks
    1
    Thanked 22 Times in 22 Posts
    If you just want to clone an array you can make do with:
    Code:
    var newArray = [].concat(oldArray);
    However if you want a deep copy of a nested non-primitive object (for example an array holding objects that might in turn hold arrays) try something like:

    Code:
    // clone a javascript object
      var clone=function(obj) {
        if (obj == undefined) return;
        if (obj.push) {
          var out = [], i = 0, len = obj.length;
          for (i=0;i<len; i++ ) {
            out[i] = arguments.callee(obj[i]);
          }
          return out;
        }
        else if (typeof obj == 'object') {
          var out = {}, i;
          for ( i in obj ) {
            out[i] = arguments.callee(obj[i]);
          }
          return out;
        }
        return obj;
      };

  • Users who have thanked ironboy for this post:

    blaze4218 (10-06-2011)

  • #8
    Regular Coder
    Join Date
    Aug 2010
    Posts
    974
    Thanks
    19
    Thanked 212 Times in 210 Posts
    Quote Originally Posted by ironboy View Post
    If you just want to clone an array you can make do with:
    Code:
    var newArray = [].concat(oldArray);
    However if you want a deep copy of a nested non-primitive object (for example an array holding objects that might in turn hold arrays) try something like:

    Code:
    // clone a javascript object
      var clone=function(obj) {
        if (obj == undefined) return;
        if (obj.push) {
          var out = [], i = 0, len = obj.length;
          for (i=0;i<len; i++ ) {
            out[i] = arguments.callee(obj[i]);
          }
          return out;
        }
        else if (typeof obj == 'object') {
          var out = {}, i;
          for ( i in obj ) {
            out[i] = arguments.callee(obj[i]);
          }
          return out;
        }
        return obj;
      };
    This would be the more modern
    method and much more understandable ...


    Code:
    function clone(obj) {
        if (obj == undefined) return;
        if (obj.push) {
          var out = [], i = 0, len = obj.length;
          for (i=0;i<len; i++ ) {
            out[i] = clone(obj[i]);
          }
          return out;
        }
        else if (typeof obj == 'object') {
          var out = {}, i;
          for ( i in obj ) {
            out[i] = clone(obj[i]);
          }
          return out;
        }
        return obj;
      };

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,947
    Thanks
    79
    Thanked 4,424 Times in 4,389 Posts
    Quote Originally Posted by ironboy View Post
    If you just want to clone an array you can make do with:
    Code:
    var newArray = [].concat(oldArray);
    DOH on me!

    I even used that exact code no more than 3 weeks ago in another answer in this forum! How soon we forget when we get old and senile.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #10
    Regular Coder
    Join Date
    Apr 2005
    Location
    Texas
    Posts
    448
    Thanks
    24
    Thanked 63 Times in 63 Posts
    Thanks to you both. @Old Pedant, your lesson was invaluable as always, @ironboy that was exactly what I was looking for... GoTeam


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •