...

View Full Version : Unexpected behavior of object



blaze4218
10-05-2011, 09:24 PM
Ok, so I wanted to use the following object to copy the contents of the Report array at index [file][entry].


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


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



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.

Old Pedant
10-05-2011, 10:20 PM
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.

Old Pedant
10-05-2011, 10:23 PM
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.

blaze4218
10-05-2011, 10:32 PM
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/10/javascript-cloning-objects/


function clone(o) {
return eval(uneval(o));
}


http://stackoverflow.com/questions/728360/copying-an-object-in-javascript


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?

Old Pedant
10-05-2011, 11:12 PM
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:


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.

Old Pedant
10-05-2011, 11:14 PM
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/>

ironboy
10-05-2011, 11:21 PM
If you just want to clone an array you can make do with:

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:


// 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;
};

DaveyErwin
10-06-2011, 01:38 AM
If you just want to clone an array you can make do with:

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:


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



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;
};

Old Pedant
10-06-2011, 01:53 AM
If you just want to clone an array you can make do with:

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.

blaze4218
10-06-2011, 04:44 AM
Thanks to you both. @Old Pedant, your lesson was invaluable as always, @ironboy that was exactly what I was looking for... GoTeam :)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum