Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Javascript (http://www.velocityreviews.com/forums/f68-javascript.html)
-   -   Duplicating objects (http://www.velocityreviews.com/forums/t921762-duplicating-objects.html)

Christopher Benson-Manica 12-06-2005 08:37 PM

Duplicating objects
 
Is there a general mechanism to duplicate, or provide for the
duplication of, objects? As an example, suppose I need to duplicate
an array. I can accomplish this with array.slice( 0 ), but that's not
going to cut in general. I could also add a copy method to the Array
prototype, like so:

Array.prototype.copy=function() {
var newArray=[];
for( var idx=0; idx < this.length; idx++ ) {
newArray.push( this[idx] );
}
return newArray;
}

and I could write similar copy() methods for various objects. But I
feel certain that I'm not the first programmer who has had a need for
such functionality. What is the canonical way of doing this?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

Evertjan. 12-06-2005 08:53 PM

Re: Duplicating objects
 
Christopher Benson-Manica wrote on 06 dec 2005 in comp.lang.javascript:

> Is there a general mechanism to duplicate, or provide for the
> duplication of, objects? As an example, suppose I need to duplicate
> an array. I can accomplish this with array.slice( 0 ), but that's not
> going to cut in general. I could also add a copy method to the Array
> prototype, like so:
>
> Array.prototype.copy=function() {
> var newArray=[];
> for( var idx=0; idx < this.length; idx++ ) {
> newArray.push( this[idx] );
> }
> return newArray;
>}
>


Array.prototype.copy=function() {
return this.concat();
}

or simply us an empty .concat() by itself:


var b = a.concat()


--
Evertjan.
The Netherlands.
(Replace all crosses with dots in my emailaddress)


VK 12-06-2005 09:00 PM

Re: Duplicating objects
 

Christopher Benson-Manica wrote:
> Is there a general mechanism to duplicate, or provide for the
> duplication of, objects? As an example, suppose I need to duplicate
> an array. I can accomplish this with array.slice( 0 ), but that's not
> going to cut in general. I could also add a copy method to the Array
> prototype, like so:
>
> Array.prototype.copy=function() {
> var newArray=[];
> for( var idx=0; idx < this.length; idx++ ) {
> newArray.push( this[idx] );
> }
> return newArray;
> }
>
> and I could write similar copy() methods for various objects. But I
> feel certain that I'm not the first programmer who has had a need for
> such functionality. What is the canonical way of doing this?


There is not such so feel free to propose one ;-)
JavaScript object doesn't have clone() method.

So in case of array your options are:
1) If array doesn't have other arrays in it (psi-"single-dimention")
you use:
var arrayOneCopy = arrayOne.slice(0);

2) If array does have other arrays in it (psi-"multi-dimention") you
use your code but just make it *recursive* and check for each single
element if it's not an array.

3) Also if you don't mind of JSON then you can

var arrayOneCopy = JSON.parse(JSON.stringify(arrayOne));


Christopher Benson-Manica 12-06-2005 09:26 PM

Re: Duplicating objects
 
<1133902815.432020.271870@g14g2000cwa.googlegroups .com>
VK <schools_ring@yahoo.com> wrote:

> There is not such so feel free to propose one ;-)


Surely someone has already done so? I can't imagine I'm the first
person who's wanted duplicated objects...

> JavaScript object doesn't have clone() method.


Any particular reason for that?

> 2) If array does have other arrays in it (psi-"multi-dimention") you
> use your code but just make it *recursive* and check for each single
> element if it's not an array.


Well, as long as I'm proposing things...

Object.prototype.copy=function( deep ) {
return this; // Use references by default
}

Array.prototype.copy=function( deep ) {
var c=[];
for( var idx=0; idx < this.length; idx++ ) {
if( deep ) {
c.push( this[idx].copy(true) );
}
else {
c.push( this[idx] );
}
}
return c;
}

--
Christopher Benson-Manica
ataru(at)cyberspace.org

Christopher Benson-Manica 12-06-2005 09:44 PM

Re: Duplicating objects
 
Christopher Benson-Manica <ataru@nospam.cyberspace.org> wrote:

> Array.prototype.copy=function( deep ) {
> var c=[];
> for( var idx=0; idx < this.length; idx++ ) {
> if( deep ) {
> c.push( this[idx].copy(true) );
> }
> else {
> c.push( this[idx] );
> }
> }
> return c;
> }


Let me try again:

Array.prototype.copy=function( deep ) {
if( !deep ) {
return this.concat();
}
var c=[];
for( var idx=0; idx < this.length; idx++ ) {
c.push( this[idx].copy(true) );
}
return c;
}

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

RobG 12-06-2005 10:29 PM

Re: Duplicating objects
 
Christopher Benson-Manica wrote:
> Christopher Benson-Manica <ataru@nospam.cyberspace.org> wrote:
>
>
>>Array.prototype.copy=function( deep ) {
>> var c=[];
>> for( var idx=0; idx < this.length; idx++ ) {
>> if( deep ) {
>> c.push( this[idx].copy(true) );
>> }
>> else {
>> c.push( this[idx] );
>> }
>> }
>> return c;
>>}

>
>
> Let me try again:
>
> Array.prototype.copy=function( deep ) {
> if( !deep ) {
> return this.concat();
> }
> var c=[];
> for( var idx=0; idx < this.length; idx++ ) {
> c.push( this[idx].copy(true) );
> }
> return c;
> }
>


That will only work where all the elements of the array are arrays, and
it fails when it gets to elements that aren't arrays.

Here's my test:

var a = [[1,2,3],1,2,3];
var b = a.copy(true); // 'this[idx].copy is not a function'
a[0][1] *=5;
alert(a[0] + '\n' + b[0]);

Here's a copy method based on something I wrote some time ago to copy
multi-dimensional arrays:

Array.prototype.copy=function() {
var A = this;
var B = [];
for (var i=0, j=A.length; i<j; ++i){
if (typeof A[i] == 'object' && Array == A[i].constructor ){
B[i] = arrayCopy(A[i]);
} else {
B[i] = A[i];
}
}
return B;
}

It is very much slower than concat(), but for small arrays it may be OK.

It will also only work on arrays of primitives, it will not work if an
element is an object other than an array. You could extend it to handle
other types of objects, but that's pretty much what JSON.parse does, so
VK's JSON.parse suggestion may be better.

<URL:http://www.crockford.com/JSON/js.html>

--
Rob

Richard Cornford 12-06-2005 11:21 PM

Re: Duplicating objects
 
Christopher Benson-Manica wrote:
> Is there a general mechanism to duplicate, or provide
> for the duplication of, objects?


No.

> As an example, suppose I need to duplicate
> an array. I can accomplish this with array.slice( 0 ),
> but that's not going to cut in general. ...

<snip>
> and I could write similar copy() methods for various
> objects. But I feel certain that I'm not the first
> programmer who has had a need for such functionality.


You are not but the reason for copying an object has a big influence
upon how you would go about it. For example, prototype-based clones can
be useful:-

var protoCloneObject = (function(){
function constr(){
;
}
return (function(obj){
constr.prototype = obj;
return new constr();
});
})();

- so that you can create an object as:-

var firstObj = new SomeObject(x, y, z);

- and then create a new object that has all of the properties and
methods of the first object with:-

var clone = protoCloneObject(firstObj);

- but is still a distinct object instance. With the significant proviso
that acting upon the copy will modify the copy but acting upon the first
object will also modify all of its copies until those copies have been
modified in a way that masks the changes in their prototype.

So in some circumstances the result is exactly what you need, and in
others it is extremely dubious.

> What is the canonical way of doing this?


There isn't, and there probably should not be one.

Richard.



Christopher Benson-Manica 12-07-2005 01:09 AM

Re: Duplicating objects
 
RobG <rgqld@iinet.net.au> wrote:

> That will only work where all the elements of the array are arrays, and
> it fails when it gets to elements that aren't arrays.


Well, in my previous post, I had

Object.prototype.copy=function() {
return this;
}

which should make it conceptually a no-op except for classes which
overrride copy.

> It will also only work on arrays of primitives, it will not work if an
> element is an object other than an array. You could extend it to handle
> other types of objects, but that's pretty much what JSON.parse does, so
> VK's JSON.parse suggestion may be better.


I will take a look at that in the morning; thanks.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.

884443zf@gmail.com 12-07-2005 02:12 AM

Re: Duplicating objects
 
sure!


Thomas 'PointedEars' Lahn 12-08-2005 02:19 PM

Re: Duplicating objects
 
Christopher Benson-Manica wrote:

> RobG <rgqld@iinet.net.au> wrote:
>> That will only work where all the elements of the array are arrays, and
>> it fails when it gets to elements that aren't arrays.

>
> Well, in my previous post, I had
>
> Object.prototype.copy=function() {
> return this;
> }
>
> which should make it conceptually a no-op except for classes which
> overrride copy.


Again: there are _no_ classes in the languages usually discussed
here (ECMAScript implementations in a client-side environment);
those are OO languages using prototype-based inheritance.

Your method returns a reference to the calling object; that is not
copying an object, it is retrieving a reference to that object.
Given your prototype method above:

var x = {foo: 'bar'}; // x.foo == 'bar'
var y = x.copy(); // y.foo == 'bar'
y.foo = 42; // y.foo == 42
alert(x.foo); // 42 (not 'bar')

Graphically, that is:

1. object1
2. x --------> object1
3. x --------> object1 <-------- y

What you wanted is:

1. object1
1. x --------> object1
2. object2
3. Copy all properties and property values from object1 to object2.
4. object2 <-------- y


PointedEars


All times are GMT. The time now is 05:13 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.