Deep Clone Modeling Backbone.js

I work in jquery with backbone.js and run the case where I need to duplicate models, but I need to make a deep copy on them, so there are no links between the copies. Models may have other models as attributes. Models can have anonymous functions as attributes.

So, I am working on creating an algorithm that will deeply clone most basic models. I expect that all bindings should be removed (for a new instance) during this copy so that I don't worry about trying to save them.

Purpose:

  • The ability to duplicate the entire simple variable (String, Int, float, etc.) and store it in a new model with the same name.
    • Done, using toJSON to create a new JSON object that can be passed to set (). This object contains only simple attributes, i.e. Does not include attributes assigned to functions or other models.
  • The ability to duplicate the functions of the annonances, which will be assigned variables, without knowing in advance the names of functions / attributes.
    • If I know the name of the attribute assigned to the function, I can copy it. But if the model is new or unknown, I do not have this information.
  • If the attribute is another base model, call the deep copy algorithm recursively on that attribute.
    • It is not possible to check if an attribute is a base model with its own baseline methods when looking for work.

A simplified version of what I currently have:

 / **
  * Performs a deep copy of a backbone.js model
  * All bindings for the copy are lost
  * @param orgModel - the original model to copy
  * /
 function deepCopyModel (orgModel)
 {   
     var dupModel = Backbone.Model.extend ({});

     var orgAttributes = orgModel.toJSON ();

     var keepAttr = _. keys (orgAttributes);
     // remove any special cases
     keepAttr = _. without (keepAttr, 'specialCase1', 'specialCase2');
     // or keepAttr = _. difference (keepAttr, ['specialCase1', 'specialCase2']);

     // remove undefined values
     keepAttr = _. filter (keepAttr, function (key) {
         return (typeof (attributes [key])! = "undefined");
     });
     // grab the resulting list of attributes after filtering
     var result = _. pick (attributes, keepAttr);
     // assign attributes to the copy using set
     dupModel.set (result);

     // TODO: Implement deep copy of functions

     // TODO: Implement deep copy of inner models

         return dupModel;
 }

Any help or insight you can give will be greatly appreciated. Thanks!

+8
javascript jquery jquery-mobile
source share
2 answers

The jQuery extend method allows you to simply copy the properties of an object from one to another.

Here is a contrived but illustrative example. It even shows why you don't need β€œdeep” copy features!

 var someObj = { a : "a", b : 12345, c : { d : "d", e : "e" }, f : function() { alert(this.a); } }; //copy from original to new empty object var deepCopy = $.extend(true, {}, someObj); deepCopy.a = "deepCopy.a"; deepCopy.cd = "deepCopy.cd"; alert("someObj is not affected when deep copying: " + someObj.cd); alert("deepCopy is entirely distinct when deep copying: " + deepCopy.cd); deepCopy.f(); someObj.f(); 

Here is the fiddle for your convenience: http://jsfiddle.net/S6p3F/3/

Running this code, you will see that someObj and deepCopy identical in structure, but to separate objects.

As you can see, deep copying of functions is not required, since the this link is tied to any object to which the function applies. This is because in javascript, calling the deepCopy.f() function is functionally equivalent to deepCopy.f.call(deepCopy) . A more illustrative example:

 function someFunction() { alert(this.someProperty); } var a = { someProperty: "a property" }, b = { someProperty: "b property" }; someFunction.call(a); someFunction.call(b); 

And the fiddle: http://jsfiddle.net/S6p3F/2/

+11
source share

If you use Lo-Dash as a replacement in the Underscore submenu, you can also use _. cloneDeep

 var newModel = new MyModel(_.cloneDeep(oldModel.toJSON()); 
+4
source share

All Articles