0

I am trying to build small functions to simulate Class related functionalities (ok, I know about frameworks).

In the following example, the code almost work, it fails on deep cloning, somehow the Test.options.* fails to clone/copy, in all created objects options.* is the same reference, any idea what I have been doing wrong?

//* class lib *//
function clone(o) {
    var tmp = new o.constructor();
    tmp.__proto__ = o;
    return tmp;
};
var Class = function(o) {
    var tmp = new Function();
    tmp.prototype = clone(o);
    return tmp;
};
//*/

//* object schema *//
var Test = new Class({
    deep: "yes",
    options: {
        inside: true
    }
});
//*/

//* object Test 1 *//
var t1 = new Test();
console.log(t1.deep); // "yes"
t1.deep = "no";
console.log(t1.deep); // "no"
console.log(t1.options.inside); // true
t1.options.inside = false;
console.log(t1.options.inside); // false
//*/

//* object Test 2 *//
var t2 = new Test();
console.log(t2.deep); // "yes"
console.log(t2.options.inside); // should be true but I get false

2 Answers 2

1

Like this?

http://overset.org/2007/07/11/javascript-recursive-object-copy-deep-object-copy-pass-by-value/

As noted there, if you're using jQuery, you already have this functionality:

http://docs.jquery.com/Utilities/jQuery.extend

Sign up to request clarification or add additional context in comments.

2 Comments

You can even use the jQuery extend function by just pulling it out of jQuery. It only makes a reference to two, very small other functions in jQuery. Then you could do obj_new = extend({}, obj_old) - and the jQuery extend function is sure to be crossbrowser.
Don't you need to run a deep extend? A deep clone should be the equivalent to running 'new' on the object. A completely new instance with no shared children.
0

I know this is not a complete answer but consider that proto is only available in mozilla engines (I am assuming you are using Rhino here).

Logically your clone is actually wrong. You are not understanding prototypes here.

A prototype is an object to look up a property in if the parent of the prototype does not contain it (think about it that way). Which means that the following code IS true in your clone structure.

var t1 = new Test(); // test object created
var t2 = new Test(); // test object 2 created
t1.options.inside = false;
t2.options.inside; // false
t1.options.inside = true;
t1.options = { inside: false };
t1.options.inside; // false
t2.options.inside; // true

This is because options is a shared reference in the prototype. Prototype never clones, it only allows your object to define a property, and thus HIDING the prototype's value.

A true clone will do something like

for(var i in o) {
    clone[i] = clone(o[i]); // deep cloning here
    clone[i] = o[i]; // shallow cloning
}

This is of course simplified because there are issues with cloning dates, strings, etc. In general cloning is not a simple task.

Check out http://javascript.crockford.com/ it covers lots of object creation mechanisms and describes prototypes well.

4 Comments

thank you based on your comment I have enhanced clone function to <code> function clone(o) { if (o == null || typeof o != "object") { return o; } var tmp = new o.constructor(); for (var key in o) { tmp[key] = clone(o[key]); } return tmp; }; </code> it still doesn't work, but I got something interesting with this code, if I do <code> var t1 = clone(new Test()); </code> instead of <code> var t1 = new Test(); </code> it will works, but I don't want to wrap my code like that
In comments you can format code by surrounding it with the back ` (backtick) character. It works in questions/answers too.
constructor is also not standard/cross-browser. And it also doesn't do what you think, and should be avoided at all times.
@bobince, how is constructor not cross-browser? Never had a problem with it. I always use it when calling my parent's constructor. You may be referring to the fact that many home-brewed class systems forget to correctly reset the constructor after chaining the prototype js-bits.blogspot.com/2010/08/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.