深度克隆Backbone.js模型

Dan*_*jan 8 javascript jquery jquery-mobile backbone.js

我正在使用backbone.js在jquery中工作并遇到需要复制模型的情况,但我需要对它们进行深层复制,因此副本之间不存在引用.模型可以将其他模型作为属性.模型可以将anon函数作为属性.

所以我正在努力创建一种能够深度克隆大多数骨干模型的算法.我希望在这个副本期间应该删除所有绑定(对于新实例),所以我不担心试图保留它们.

目标:

  • 能够复制所有简单变量(String,Int,float等)并将其存储到新模型中,作为相同的名称.
    • 完成后,使用toJSON创建一个可以传递给set()的新JSON对象.此对象仅包含简单属性,即不包括分配给函数或其他模型的属性.
  • 能够复制anon函数,一些变量将被分配给,而不事先知道函数/属性名称.
    • 如果我知道分配给函数的属性的名称,我可以复制它.但如果模型是新的或未知的,我没有那些信息.
  • 如果属性是另一个主干模型,则在该属性上递归调用深层复制算法.
    • 无法检查属性是否是具有本机骨干方法的骨干模型,正在寻找解决方法.

我目前拥有的简化版本如下:

/**
 * 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;
}

您将给予的任何帮助或见解将不胜感激.谢谢!

Wic*_*ams 11

jQuery的extend方法允许您简单地将对象属性从一个复制到另一个.

这是一个人为的,但说明性的例子.它甚至可以说明为什么你不需要"深度"复制功能!

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.c.d = "deepCopy.c.d";

alert("someObj is not affected when deep copying: " + someObj.c.d);
alert("deepCopy is entirely distinct when deep copying: " + deepCopy.c.d);

deepCopy.f();    
someObj.f();
Run Code Online (Sandbox Code Playgroud)

这里有一个方便您的小提琴:http://jsfiddle.net/S6p3F/3/

运行此代码,您将看到someObj并且deepCopy结构相同但对象不同.

如您所见,不需要深度复制函数,因为this引用绑定到函数所应用的任何对象.这是因为在javascript中,调用函数在deepCopy.f()功能上等同于deepCopy.f.call(deepCopy).更具说明性的例子:

function someFunction() {
    alert(this.someProperty);
}

var a = {
        someProperty: "a's property"
    },
    b = {
        someProperty: "b's property"
    };

someFunction.call(a);
someFunction.call(b);
Run Code Online (Sandbox Code Playgroud)

还有一个小提琴:http://jsfiddle.net/S6p3F/2/

  • 如果你提供`true`作为`extend`的第一个参数,它确实会做一个深层复制.更新示例以反映此情况.至于封闭等,任何对JS有合理理解的人都会理解这一点.我的观点并不是它在所有情况下都能工作,但复制函数引用通常都是需要的. (2认同)