Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 18

Thread: Copying Objects

  1. #1
    New Coder
    Join Date
    Jul 2002
    Posts
    30
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Copying Objects

    How would I go about copying an instance of an object? If I create a new variable and set it to equal the object, it simply make the variable a pointer to the object, rather than creating a copy of it... I'll write some code to help explain my problem better, for anyone who's confused...
    Code:
    function MyObject()
    {
    this.property1="hihi!"
    this.property2="byebye!"
    //Pretend I have a whole bunch of properties listed in here
    }
    var Blah=new MyObject()
    Blah.property1="bleh"
    Blah.property2="blah"
    //and on and on
    
    var CopyOfBlah=Blah //I want this to create a copy of Blah
    
    Blah.property1="I changed blah!"
    
    alert(CopyOfBlah.property1) //Alerts "I changed blah!"... 
    //its value should be "bleh", since I changed Blah's value, not CopyOfBlah's value, but since it isn't a real copy, 
    //whatever I do to one affects the other
    //So how do I make it a 'real' copy?

  • #2
    Regular Coder
    Join Date
    Jun 2002
    Posts
    338
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Code:
    function MyObject() {
    	this.property1="hihi!";
    	this.property2="byebye!";
    
    	this.getProps=function() {
    		var newVar=new MyObject();
    		newVar.property1=this.property1;
    		newVar.property2=this.property2;
    
    		return newVar;
    	}
    }
    var Blah=new MyObject();
    Blah.property1="bleh";
    Blah.property2="blah";
    		
    var CopyOfBlah=Blah.getProps();
    Blah.property1="I changed blah!"
    alert(CopyOfBlah.property1); //alerts "bleh"
    Hope that helps!

    Happy coding!

  • #3
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    This is too simple to be OK but....

    Code:
    <html>
    <head>
    <title>untitled</title>
    <script type="text/javascript" language="JavaScript">
    
    //////////////////////////////////////
    Object.prototype.copy = function() {
    var dupe = new Object();
    for (prop in this) dupe[prop] = this[prop];
    return dupe;
    }
    //////////////////////////////////////
    
    function MyObject(greeting, farewell) {
    this.greeting = greeting;
    this.farewell = farewell;
    }
    
    var Blah = new MyObject('hihi!', 'byebye!');
    var CopyOfBlah = Blah.copy(); //I want this to create a copy of Blah
    
    alert('BEFORE:\n\nBlah.farewell = "' + Blah.farewell + '"\nCopyOfBlah.farewell = "' + CopyOfBlah.farewell + '"');
    
    Blah.farewell = 'Buzz off!';
    
    alert('AFTER\n\nBlah.farewell = "' + Blah.farewell + '"\nCopyOfBlah.farewell = "' + CopyOfBlah.farewell + '"');
    
    </script>
    </head>
    <body>
    </body>
    </html>

  • #4
    Senior Coder joh6nn's Avatar
    Join Date
    Jun 2002
    Location
    72° W. 48' 57" , 41° N. 32' 04"
    Posts
    1,887
    Thanks
    0
    Thanked 1 Time in 1 Post
    i'm pretty sure that wouldn't work, because there are important, innumerable properties of objects, that wouldn't be copied by that. unfortunately, i don't have a better answer. the subject isn't covered at all in the Guide, and while i know you can clone nodes and such in the DOM, i've never heard of cloning objects, with or without the DOM. it was something i was looking for myself, and never came up with an answer to. Maybe Dave knows. ::crosses his fingers::
    bluemood | devedge | devmo | MS Dev Library | WebMonkey | the Guide

    i am a loser geek, crazy with an evil streak,
    yes i do believe there is a violent thing inside of me.

  • #5
    New Coder
    Join Date
    Jul 2002
    Posts
    30
    Thanks
    0
    Thanked 0 Times in 0 Posts
    As far as I can tell, adios' code works perfectly for me...
    But then again, I have no idea what properties would be considered innumerable, or why they wouldn't be copied... could someone explain for me?

  • #6
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Adios's method will not clone methods of the object, unless you are running a Gecko-based browser. Which is one *huge* problem.

  • #7
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hmh... adios' code seemed to work for me in IE5.5 and NN4.7 also for copying of the methods of the instance object... do I miss something here?

    Code:
    //////////////////////////////////////
    Object.prototype.copy = function() {
        var dupe = new Object();
    
        for (prop in this) {
            dupe[prop] = this[prop];
        }
    
        return dupe;
    }
    //////////////////////////////////////
    
    function MyObject(greeting, farewell) {
        this.greeting = greeting;
        this.farewell = farewell;
        this.eat = function(){alert("meat");}
    
        //  a nonenumerable method
        this.toString = function() {
            return "I am a string representation of me!";
        }
    }
    
    var Blah = new MyObject('hihi!', 'byebye!');
    
    //  overwrite the existing eat() method of Blah
    Blah.eat = function() { alert("vegetables"); }
    
    var CopyOfBlah = Blah.copy(); //I want this to create a copy of Blah
    
    //  test Blah
    Blah.eat();
    alert(Blah);
    
    MyObject.eat = null;
    Blah.eat = null;
    
    //  test CopyOfBlah
    CopyOfBlah.eat();
    alert(CopyOfBlah);
    What joh6nn meant about enumerable properties is shown here by defining a custom toString() method for MyObject. Since it's not enumerable and does not show up in the for...in loop, it doesn't get copied by the code above.

  • #8
    Regular Coder
    Join Date
    Jun 2002
    Location
    Round Rock, Texas
    Posts
    443
    Thanks
    0
    Thanked 0 Times in 0 Posts
    This problem of referencing, not copying an object is a classic gotcha in C++ programming. The solution is to write a copy constructor that's what nolachrymose did.

  • #9
    Senior Coder
    Join Date
    Jun 2002
    Posts
    1,404
    Thanks
    2
    Thanked 32 Times in 32 Posts
    Cloning, Part II:

    Code:
    <html>
    <head>
    <title>untitled</title>
    <style type="text/css">
    input {width:200px;}
    td {font:200 12px monospace;}
    </style>
    </head>
    <body>
    <script type="text/javascript" language="JavaScript">
    
    Object.prototype.copy = function() {
    var copy = new this.constructor;
    for (prop in this) copy[prop] = this[prop];
    return copy;
    }
    
    function MyThingy(greeting, farewell) {
    this.greeting = greeting;
    this.farewell = farewell;
    this.hello = function() {
    alert(this.greeting);
    }
    this.byebye = function() {
    alert(this.farewell);
    }
    this.toString = function() {
    return 'This is a non-enumerable method. Really.';
    }
    }
    
    var thingy = new MyThingy('Hola!', 'Adios!');
    var otherthingy = thingy.copy();
    function enumerate() {
    var a = '';
    for (clonedprops in otherthingy) 
    a += clonedprops + ': ' + otherthingy[clonedprops] + '\n';
    alert(a);
    }
    
    </script>
    <table width="100%"><tr><td>
    <form>
    <input type="button" value="Enumerate Copy Properties" 
    onclick="enumerate()"><br><br>
    <input type="button" value="Show Copy Constructor" 
    onclick="alert(otherthingy.constructor)"><br><br>
    <input type="button" value="call otherthingy.byebye()" 
    onclick="otherthingy.byebye()"><br><br>
    <input type="button" value="Change thingy.greeting" 
    onclick="thingy.greeting=prompt('Enter new greeting:','Bite me.')"><br><br>
    <input type="button" value="Show thingy.greeting" 
    onclick="alert(thingy.greeting)"><br><br>
    <input type="button" value="Show otherthingy.greeting" 
    onclick="alert(otherthingy.greeting)"><br><br>
    <input type="button" value="otherthingy.toString()" 
    onclick="alert(otherthingy.toString())">
    </form></td>
    <td>
    Object.prototype.copy = function() {<br>
    var copy = new this.constructor;<br>
    for (prop in this) copy[prop] = this[prop];<br>
    return copy;<br>
    }<br>
    <br>
    function MyThingy(greeting, farewell) {<br>
    this.greeting = greeting;<br>
    this.farewell = farewell;<br>
    this.hello = function() {<br>
    alert(this.greeting);<br>
    }<br>
    this.byebye = function() {<br>
    alert(this.farewell);<br>
    }<br>
    this.toString = function() {<br>
    return 'This is a non-enumerable method. Really.';<br>
    }<br>
    }<br>
    <br>
    var thingy = new MyThingy('Hola!', 'Adios!');<br>
    var otherthingy = thingy.copy();<br>
    function enumerate() {<br>
    var a = '';<br>
    for (clonedprops in otherthingy)<br>
    a += clonedprops + ': ' + otherthingy[clonedprops] + '\n';<br>
    alert(a);<br>
    }<br>
    </td></tr></table>
    </body>
    </html>
    ...would appreciate any comments...

    to mordred:

  • #10
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Originally posted by jkd
    Adios's method will not clone methods of the object, unless you are running a Gecko-based browser. Which is one *huge* problem.
    I apologize for my misleading and slightly incorrect statement.

    You can iterate methods in a user-defined object, but not native, host objects unless it is a Gecko browser.

    i.e. if you wanted to copy window or document, you'd only get the methods if you were running Gecko.

  • #11
    Regular Coder
    Join Date
    Jun 2002
    Location
    Round Rock, Texas
    Posts
    443
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by jkd
    Adios's method will not clone methods of the object, unless you are running a Gecko-based browser. Which is one *huge* problem.
    Ok, help me understand. The above doesn't make sense to me.

    My understanding is: methods are not copied per se. The new object is the same 'type' as the original. Thus the new object has those methods also.

    Hate to ask, but what's Gecko?

  • #12
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    Gecko is a browser engine that NS6, NS7, Mozilla, Beonex, K-meleon, and Galeon are based on.

    Anyway, my followup might relieve some of that confusion.

    Essentially, on a browser defined object, methods are not enumerated in a for...in loop.

    You know document.write() exists, but a for...in loop will never reveal the write method.

    Unless of course you are using a Gecko-based browser - in which case methods on native objects are enumerated.

    Assuming we have a copy method which uses for...in (i.e. Adios's method):

    copy(document) in non-Gecko will return an object not containing any of the methods of document, while copy(document) in Gecko will return an object with document's methods.

    But in user-defined objects, methods are enumerable. copy(MyObject) would be the same in all browsers using a for...in loop.

    That explain things any?

  • #13
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    @adios:
    Nice work how you instantiated the copied object with the constructor function.

    The only thing we have to remember is that a toString() function added to an object by invoking it's static members is not going to be represented in the copied object, since it's not present in the constructor function nor enumearble through the for loop... which in itself constitutes only a vary rare case, since I can't think of any good reason to mess around with the toString() function after the definition of an object's constructor function has been made.

  • #14
    jkd
    jkd is offline
    Senior Coder jkd's Avatar
    Join Date
    May 2002
    Location
    metro DC
    Posts
    3,163
    Thanks
    1
    Thanked 18 Times in 18 Posts
    This works for user-defined objects in Gecko btw:

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

    A custom-object's toSource() method will return a string of the literal equivalent of the object:

    function TestConstructor() {
    this.test = 1;
    this.meth = function() { alert('test') } ;
    }
    var test = new TestConstructor();
    alert(test.toSource())
    // '({test:1, meth:(function() { alert("test");})})'

    var testcopy = test.copy();
    test.test = 'something else';
    alert(testcopy.test) // 1


    For some reason user-defined objects don't seem to have a toSource() in IE, despite that being a method inherited from Object.... and NS4 complains about meth: being an invalid label.

    Just some more food for thought.

  • #15
    Senior Coder
    Join Date
    Jun 2002
    Location
    frankfurt, german banana republic
    Posts
    1,848
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Originally posted by jkd
    Unless of course you are using a Gecko-based browser - in which case methods on native objects are enumerated.
    While the methods get enumerated, poblems arise when using adios' copy method and native objects like window or location:

    Copying location and trying to invoke copyObj.replace("http://www.codingforums.com");

    throws

    "Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: <unknown filename> :: onclick :: line 0" data: no]"

    Copying window does not work at all because this error message pops up:

    "Error: uncaught exception: Permission denied to get property Window.fullScreen"

    Seems like it's not native objects available for copying but rather DOM objects... although I haven't tested this assumption in detail, it's just a premature conclusion from the errors above. I tested in Mozilla 1 with a code exactly like adios example, only this line different:

    var otherthingy = window.copy();


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •