javascript 深度克隆 Backbone.js 模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11799342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 14:23:45  来源:igfitidea点击:

Deep Cloning Backbone.js Models

javascriptjqueryjquery-mobilebackbone.js

提问by Daniel Gradinjan

I am working in jquery with backbone.js and running into the case where i need to duplicate models, but i need to do a deep copy on them so no references exist between the copies. Models can have other models as attributes. Models can have anon functions as attributes.

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

So i'm working on creating an algorithm that will deep clone most backbone models. I'm expecting that all bindings should be removed (for the new instance) during this copy so I'm not worried about trying to keep them.

所以我正在努力创建一种算法来深度克隆大多数骨干模型。我期望在此复制期间应删除所有绑定(对于新实例),因此我不担心尝试保留它们。

Goals:

目标:

  • Able to duplicate all simple variable (String, Int, float, etc) and store it into the new model, as the same name.
    • Done, using toJSON to create a new JSON object which can be passed to set(). This object only contains simple attributes, i.e. does not include attributes assigned to functions or other models.
  • Able to duplicate the anon functions some variables will be assigned to, without knowing function/attribute names beforehand.
    • If I know the name of the attribute which is assigned to a function I can copy it. But if the model is new or unknown I don't have that information.
  • If an attribute is another backbone model, call the deep copy algorithm recursively on that attribute.
    • Not able to check if an attribute is a backbone model with native backbone methods, looking for a work around.
  • 能够复制所有简单变量(字符串、整数、浮点数等)并将其以相同的名称存储到新模型中。
    • 完成,使用 toJSON 创建一个可以传递给 set() 的新 JSON 对象。该对象仅包含简单属性,即不包含分配给功能或其他模型的属性。
  • 能够复制匿名函数,一些变量将被分配给,而无需事先知道函数/属性名称。
    • 如果我知道分配给函数的属性的名称,我可以复制它。但如果模型是新的或未知的,我就没有这些信息。
  • 如果一个属性是另一个主干模型,则对该属性递归调用深复制算法。
    • 无法检查属性是否是具有本机主干方法的主干模型,正在寻找解决方法。

The simplified version of what I currently have is below:

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

/**
 * 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 would be greatly appreciated. Thanks!

您可以提供的任何帮助或见解将不胜感激。谢谢!

回答by WickyNilliams

jQuery's extendmethod allows you to simply copy object properties from one to another.

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

Here's a contrived, but illustrative example. It even shows why you would not need to "deep" copy functions!

这是一个人为但具有说明性的示例。它甚至说明了为什么您不需要“深度”复制功能!

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();

Here's a fiddle for your convenience: http://jsfiddle.net/S6p3F/3/

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

Running this code you will see that someObjand deepCopyare identical in structure but distinct objects.

运行该代码,你会看到someObjdeepCopy在结构但不同的对象相同。

As you can see, deep copying of functions is not required as the thisreference is bound to whatever object the function is applied to. This is becausein javascript, calling a function as deepCopy.f()is functionally equivalent to deepCopy.f.call(deepCopy). A more illustrative example:

如您所见,不需要对函数进行深度复制,因为this引用绑定到该函数应用于的任何对象。这是因为在 javascript 中,调用函数 asdeepCopy.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);

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

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

回答by tmaximini

If you are using Lo-Dashas Underscore drop-in replacement, you can also use _.cloneDeep

如果你使用Lo-Dash作为Underscore 的替代品,你也可以使用_.cloneDeep

var newModel = new MyModel(_.cloneDeep(oldModel.toJSON());