Search code examples
javascriptjquerycloneextend

Cloning JavaScript Objects. Again :(


I know it is really annoying to read this topic again. Before you start diggin into the code, one solution could be that I don't get prototypes and objects in JavaScript. But at this point i think, i do.

The problem is:
How to clone an JavaScript Class (created with prototypes), so that the “cloned” Class remains untouched when extending and executing afterwards?

function clone(obj){
  if(obj == null || typeof(obj) != 'object')
      return obj;

  var temp = new obj.constructor();
  for(var key in obj)
      temp[key] = clone(obj[key]);

  return temp;
}

var FOO = function() {
  var myBAR = clone(BAR);
  myBAR.prototype = jQuery.extend(true, myBAR.prototype, this); // deep cloning twice and extending with this
  console.log("FOO:", this.name);
  new myBAR();
};

FOO.prototype = {
  name: "FOO"
};

var BAR = function() {
  console.log("BAR:", this.name);
};

BAR.prototype = {
  name: "BAR"
};

new FOO(); // returns FOO: FOO and BAR: FOO 
new BAR(); // returns BAR: FOO should return BAR: BAR

If i've got it right, the second call of new BAR() (after new FOO()) should return BAR: BAR not BAR: FOO as at the moment.

One possible solution for this problem is an complete rewrite of the clone function in something like this:

function clone(obj) {
  return eval("("+obj.toString()+")"); // the same as eval(uneval(obj));
}

But this approach has an BIG downside, you can't pass any dynamically created objects.

Any ideas?


Solution

  • I just wanted to show anyone my solution for the problem above.

    function cloneClass (func) {
    
      if(typeof func == 'function') {
    
        var prototype = {};
        for (var prop in func.prototype) {
          prototype[prop] = func.prototype[prop];
        };
    
        var Class = function() {
          var _this = this;
          var constructor = function() {
            func.apply(_this, arguments);
          };
          constructor.prototype = _this;
    
          for (var property in func) {
            if(property != "prototype") {
              constructor[property] = func[property];
            }
          };
    
          return constructor;
        };
    
        Class.prototype = prototype;
        return new Class();
      }
    
      return func;
    
    };
    

    Try to dig into it to understand how this is working. Does anyone can see any problems with this implementation, memory leaks etc.?