> True use-cases for deep-cloning are actually pretty rare.

I'll second that.

> I'm not sure what you are attempting to do here, but there's most
> certainly a better way of doing it without needing deep-cloning.

I think I'd go with "probably". :-)

But yeah, buda, you might want to step back and look at what you're
really trying to accomplish.  Maybe you need deep cloning, but in
(let's see...) 17 years as a professional software engineer on a
variety of platforms, I've only really needed to do it a couple of
times...
--
T.J. Crowder
tj / crowder software / com

On Oct 8, 2:51 pm, Tobie Langel <[EMAIL PROTECTED]> wrote:
> True use-cases for deep-cloning are actually pretty rare.
>
> When bumping into such an issue, it's usually a good idea to look for
> a better coding pattern rather than to add complexity, augment memory
> consumption and worsen the performance by bringing out the big guns.
>
> I'm not sure what you are attempting to do here, but there's most
> certainly a better way of doing it without needing deep-cloning.
>
> Just my two-cents.
>
> Best,
>
> Tobie
>
> On Oct 8, 2:05 pm, "T.J. Crowder" <[EMAIL PROTECTED]> wrote:
>
> > Hi,
>
> > Object.clone is documented as being a shallow 
> > copy:http://www.prototypejs.org/api/object/clone
>
> > "Deep" cloning is more complicated than it seems at first.  A naive
> > version would be along these lines:
>
> > Object.extend(Object, {
> >     deepClone: function(source) {
> >         var result;
> >         var property;
> >         var val;
>
> >         result = {};
> >         for (property in source)
> >         {
> >             val = source[property];
> >             if (typeof val == "object" && !Object.isFunction(val))
> >             {
> >                 result[property] = Object.deepClone(val);
> >             }
> >             else
> >             {
> >                 result[property] = val;
> >             }
> >         }
> >         return result;
> >     }
>
> > });
>
> > Caveat: I'm not at all sure "typeof val == 'object' && !
> > Object.isFunction(val)" is an adequate check for whether we should
> > clone the property.
>
> > BUT, note that that does NOT correctly handle the full object graph.
> > Consider:
>
> >     var a, thing;
>
> >     thing = { name: 'original' };
> >     a = {};
> >     a.first = thing;
> >     a.second = thing;
>
> >     a.first.name = 'changed';
>
> > At this point, a.first.name and a.second.name both have the value
> > 'changed'.  But if you used the deepClone above before changing it:
>
> >     var a, thing;
>
> >     thing = { name: 'original' };
> >     a = {};
> >     a.first = thing;
> >     a.second = thing;
>
> >     a = Object.deepClone(a); // <= ADDED THIS
>
> >     a.first.name = 'changed';
>
> > ...then a.first.name is 'changed' but a.second.name is 'original'.
> > The "deep" clone is not a correct clone, because it didn't recognise
> > that two properties referenced the same instance.
>
> > It gets even worse if the object refers to itself, as the deepClone
> > function above would infinitely recurse.
>
> > Handling the full graph correctly would require that during a
> > particular cloning operation, you maintained a bag of cloned objects
> > keyed by *identity* (===) and reused the clones if you'd already
> > cloned them in the past.  Something like this:
>
> > (On pastie:http://pastie.org/287641)
> > * * * * * *
> > /**
> >  * A very quick-and-dirty bag for having values associated with  * a
> > key that's compared by
> >  * identity (===)
> >  */
> > var SlowIdentityBag = Class.create({
>
> >     /**
> >      * Create an empty bag.
> >      */
> >     initialize: function() {
> >         this.items = [];
> >     },
>
> >     /**
> >      * Get an entry from the bag for the given key.
> >      *
> >      * @param   key     The key to search for
> >      * @return  the associated value, or undefined if not found
> >      */
> >     get: function(key) {
> >         var index;
> >         var entry;
>
> >         for (index = this.items.length - 1; index >= 0; --index)
> >         {
> >             entry = this.items[index];
> >             if (entry.key === key)
> >             {
> >                 return entry.val;
> >             }
> >         }
>
> >         return undefined;
> >     },
>
> >     /**
> >      * Put the given value in the bag with the given key.
> >      *
> >      * @param   key     Take a wild guess
> >      * @param   val     See above
> >      */
> >     put: function(key, val) {
>
> >         this.items.push({ key: key, val: val});
> >     }
>
> > });
>
> > Object.extend(Object, {
> >     /**
> >      * Deeply clone an object, preserving the object graph by only
> > cloning each object once and
> >      * reusing it if necessary.
> >      *
> >      * @param   source              The source object to clone
> >      * @param   clonesByIdentity    Usually omitted; if given, a
> > SlowIdentityBag containing
> >      *                              previously-cloned objects to reuse
> > keyed by the originals.
> >      *                              MUST NOT contain 'source'.
> >      */
> >     deepClone: function(source, clonesByIdentity) {
> >         var result;
> >         var property;
> >         var val;
>
> >         // A blank result object
> >         result = {};
>
> >         // Usually we create this unless we're calling ourselves
> >         if (!clonesByIdentity)
> >         {
> >             clonesByIdentity = new SlowIdentityBag();
> >         }
>
> >         // The source may be self-referential, so remember the
> > instance
> >         // we're cloning it to at the outset
> >         clonesByIdentity.put(source, result);
>
> >         // Process the properties
> >         for (property in source)
> >         {
> >             val = source[property];
> >             if (typeof val == "object" && !Object.isFunction(val))
> >             {
> >                 // Something we should clone, if we haven't already.
> >                 // (That check is probably not adequate.)
> >                 // Grab it or clone it.  Note that deepClone will
> >                 // add it to the bag.
> >                 val = clonesByIdentity.get(val) ||
> > Object.deepClone(val, clonesByIdentity);
> >             }
> >             result[property] = val;
> >         }
> >         return result;
> >     }});
>
> > * * * * * *
>
> > Caveats on that:
>
> > 1. This is very much off-the-cuff.
> > 2. Same caveat as earlier about the check for whether to clone the
> > object.
> > 3. I can't imagine it's all that fast.  Offhand I couldn't think of a
> > faster way to do the SlowIdentityBag; anyone have a l33t idea there?
>
> > FWIW,
> > --
> > T.J. Crowder
> > tj / crowder software / com
>
> > On Oct 8, 4:18 am, buda <[EMAIL PROTECTED]> wrote:
>
> > > I have an object
>
> > > var obj = {
> > >   info: {
> > >     section:{
> > >       CountryCities:{
> > >          filter: {
> > >             CountryID: 'MyCountry'
> > >          }
> > >       }
> > >     }
> > >   }
>
> > > }
>
> > > var arg = Object.clone(obj);
> > > arg.info.section.CountryCities.CountryID = '100';
>
> > > or
>
> > > var arg = Object.extend({}, obj);
> > > arg.info.section.CountryCities.CountryID = '100';
>
> > > do the same =>
> > > arg.info.section.CountryCities.CountryID =
> > > obj.info.section.CountryCities.CountryID = 100
>
> > > but I need an independent copy of an obj in arg!!!!!
>
> > > How could I do it?
>
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Prototype & script.aculo.us" group.
To post to this group, send email to prototype-scriptaculous@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to