By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
426,165 Members | 1,916 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 426,165 IT Pros & Developers. It's quick & easy.

Copying objects

P: n/a
Hi!

If A is an object, then "B = A;" will just assign a reference. Isn't there a
simple way to create an actual copy of A and assign that to B?

Greetings,
Thomas

Jul 20 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
"Thomas Mlynarczyk" <bl*************@hotmail.com> writes:
If A is an object, then "B = A;" will just assign a reference. Isn't there a
simple way to create an actual copy of A and assign that to B?


No, not in general.

There are several ways to do something that resembles it, though, and
depending on the objects' nature and how you intend to use the copy,
you can pick the one that suits you best.

If it is a plain object, you can find all the properties you have added
using enumeration, and assign them to another object:

function copyByEnum(object) {
var copyObject = new Object();
for(var property in object) {
copyObject[property] = object[property];
}
return copyObject;
}

This will not work if the object is not a plain object, but, e.g., a
function or array. It will only copy enumerable properties. On an
Object (something created by the user using only "new Object()" and
inheritance), the only non-enumerable properties are the ones in
Object.prototype. The new copy will also have these because it is
created with "new Object()".

If you want to clone an Array, you can first try to detect that it
is an Array, and then use "copy = new Array(object.length)" instead
of "copy = new Object()". Detection isn't that easy, and it won't
help you for functions.

If you don't want to copy all the properties manually, you can use
prototype-based inheritance. In a prototype based language like
Javascript, inheritance happens directly between objects, and not
through classes as in, e.g., Java. The object you inherit from
is called the "prototype", and when you look up properties,
the ones not found in the new object itself are then searched for
in its prototype. Assignments will write to the new object directly.

function copyByInheritance(object) {
function dummyConstructor(){};
dummyConstructor.prototype = object;
return new dummyConstructor();
}

Again, it won't work for host objects like Arrays and Functions.
These copy methods have been shallow copies. If one of the properties
of the object is itself an object, only its reference is copied. If
you want a deep copy, you will need to look at each property and
determine whether it is an object that should be deep-copied again.

All in all, you need a good reason before you start doing any of
this :)
/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #2

P: n/a
"Thomas Mlynarczyk" <bl*************@hotmail.com> wrote:
If A is an object, then "B = A;" will just assign a reference. Isn't there a simple way to create an actual copy of A and assign that to B?


b = a.clone();
(lowercase letters denote an instance of a class.)

You have to implement the method for each class you write, if you want it to
be cloneable. It's not always simple-- if your object contains references
to other objects, and those contain references to... You have to decide how
deep of a copy to make.

--
Wendy Smoak
Jul 20 '05 #3

P: n/a
"Wendy S" <we******@hotmail.com> writes:
b = a.clone();
(lowercase letters denote an instance of a class.)
I''d say they denote objects. There Are No Classes In Javascript(TM)
(or, if we define something to be called "classes", it will not match,
e.g., Java's notion of a class very well).
You have to implement the method for each class you write, if you want it to
be cloneable. It's not always simple--


Or even possible. In IE (or pretty much anything except Gecko based browsers),
you can't add to the prototype of DOM nodes.

(You should also be careful not to clone the clone functions
unecessarily :)

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #4

P: n/a
Also sprach Lasse Reichstein Nielsen:
If it is a plain object, you can find all the properties you have
added using enumeration, and assign them to another object:

function copyByEnum(object) {
var copyObject = new Object();
for(var property in object) {
copyObject[property] = object[property];
}
return copyObject;
}

This will not work if the object is not a plain object, but, e.g., a
function or array. It will only copy enumerable properties.


Thanks for your reply. Meanwhile I have come up with the following:

function copy(s) {
for(p in s)
this[p] = (typeof(s[p]) == 'object')? new copy(s[p]) : s[p];
}

a = new copy(b);

It seems to work as intended. But I haven't yet considered the issue of
arrays or functions. But shouldn't the above work as well with arrays? Are
arrays assigned by reference too, like objects? If so, then I should change
my typeof test to (typeof(s[p]) == 'object' || typeof(s[p]) == 'array').
Would it work for functions too as expected?

Greetings,
Thomas
Jul 20 '05 #5

P: n/a
"Lasse Reichstein Nielsen" <lr*@hotpop.com> wrote in message
news:sm**********@hotpop.com...
I''d say they denote objects. There Are No Classes In Javascript(TM)
(or, if we define something to be called "classes", it will not match,
e.g., Java's notion of a class very well).


My apologies! I didn't notice which group the question was posted in and
assumed I was in comp.lang.java.

--
Wendy in Chandler, AZ

Jul 20 '05 #6

P: n/a
"Thomas Mlynarczyk" <bl*************@hotmail.com> writes:
But shouldn't the above work as well with arrays?
It won't. The copy will be an instance of Object, not Array, so it
won't be an array - just an object with property names that look like
numbers.
Are arrays assigned by reference too, like objects?
Arrays are objects. They are host objects, so they can act differently
from user defined objects. You can't inherit "arrayness". You must be
created as an array (either using the constructor "new Array(2,3)" or
a literal "[2,3]").
If so, then I should change my typeof test to (typeof(s[p]) ==
'object' || typeof(s[p]) == 'array'). Would it work for functions
too as expected?


The problem is that "typeof [1,2]" is "object". You have to detect
arrays differently, and there is no absolutely certain way to do
that. You can try testing with
perhapsArray.constructor == Array
perhapsArray instanceOf Array
Array.prototype.isPrototypeOf(perhapsArray)
but they can all be fooled.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #7

P: n/a
Also sprach Lasse Reichstein Nielsen:
But shouldn't the above work as well with arrays?
It won't. The copy will be an instance of Object, not Array, so it
won't be an array - just an object with property names that look like
numbers.


Ah, I see. So, for practical purposes, my code would copy arrays too, but
not into arrays but objects. The implications would be that I could no
longer use any array specific methods (like join) or properties (like
length) on the result. In addition, my code will convert any properties
which are arrays into objects as well.
perhapsArray.constructor == Array
perhapsArray instanceOf Array
Array.prototype.isPrototypeOf(perhapsArray)
but they can all be fooled.


How could they be fooled? If the array has non-numeric indices? But then it
would be treated as an object anyway, wouldn't it?
Jul 20 '05 #8

P: n/a
"Thomas Mlynarczyk" <bl*************@hotmail.com> writes:
Also sprach Lasse Reichstein Nielsen:

perhapsArray.constructor == Array
perhapsArray instanceOf Array
Array.prototype.isPrototypeOf(perhapsArray)
but they can all be fooled.


How could they be fooled? If the array has non-numeric indices? But then it
would be treated as an object anyway, wouldn't it?


---
function dummyConstructor(){};
dummyConstructor.prototype = new Array();
var nonArray = new dummyConstructor();

alert(nonArray.constructor == Array);
alert(nonArray instanceof Array);
alert(Array.prototype.isPrototypeOf(nonArray));

nonArray[100]=100;
alert(nonArray.length); // not an array after all.
---

You can try testing for array-like behavior:
---
function probablyArray(obj) {
if (! obj.hasOwnProperty("length")) {return false;}
var n = obj.length;
if (obj.hasOwnProperty(n)) {return false;}
obj[n]=true;
if (obj.length != n+1) {return false;}
obj.length = n;
if (obj.hasOwnProperty(n)) {return false;}
return true;
}
---
However, in some browsers, you might be able to make things act like
an array against any test, and still not be an array.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.