Search code examples
javascriptjqueryclone

Is there a way to reassign an argument within a function, and have it also affect the calling scope?


What I am trying to do is build a clone() function for Javascript objects. As you know the lack of native functionality for this in Javascript can be a pain. I have a great method to do it, but usability wise, it is awkward. Here is the function so far:

function clone(objectToClone) {
    var myClone = function() {};
    myClone.prototype = objectToClone;
    return [
        new myClone(),
        new myClone()
    ];
}

As you can see, currently I just return an array with both clones. This makes the usage look something like this:

// usage
var bar = new foo();
bar = clone(bar); // forks bar into two separate copies of bar (awkward)
// bar[0] is now clone 1
// bar[1] is now clone 2

What I would like to do, is be able to do something like the following:

function clone(objectToClone) {
    var myClone = function() {};
    myClone.prototype = objectToClone;
    objectToClone = new myClone(); // somehow magically?
    return new myClone();
}

// usage
var bar = new foo();
var baz = clone(bar); // returns a copy, and bar is now one of the copies as well.
// bar is now clone 1
// baz is now clone 2

Unfortunately this does not work, since assigning the argument does not affect the calling scope. I was hoping that someone might be able to help think up some js trickery that would allow me to use the function in the desired manor however. Any ideas are greatly appreciated.


Solution

  • To get your desired result, you would need to pass in an object with properties and then modify those properties. That's the best way to get a reference in javascript that allows you to change the original. You cannot change the original when it's just passed as an ordinary function argument. Javascript doesn't have those types of references.

    function clone(holder) {
        var myClone = function() {};
        myClone.prototype = holder.input;
        holder.input = new myClone(); // somehow magically?
        return new myClone();
    }
    
    // usage
    var holder = {};
    var holder.input = new foo();
    var holder.output = clone(holder); // returns a copy, and holder.input is now a copy too
    // holder.input is now clone 1
    // holder.putput is now clone 2