8

私はbackbone.jsを使用してjqueryで作業しており、モデルを複製する必要がある場合に遭遇していますが、コピー間に参照が存在しないように、モデルに対してディープコピーを実行する必要があります。モデルは、属性として他のモデルを持つことができます。モデルは、属性としてanon関数を持つことができます。

そのため、ほとんどのバックボーンモデルのクローンを作成するアルゴリズムの作成に取り組んでいます。このコピー中にすべてのバインディングが(新しいインスタンスに対して)削除されることを期待しているので、それらを保持しようとする心配はありません。

目標:

  • すべての単純な変数(String、Int、floatなど)を複製して、同じ名前で新しいモデルに格納できます。
    • 完了しました。toJSONを使用して、set()に渡すことができる新しいJSONオブジェクトを作成します。このオブジェクトには単純な属性のみが含まれます。つまり、関数や他のモデルに割り当てられた属性は含まれません。
  • 関数/属性名を事前に知らなくても、一部の変数が割り当てられるanon関数を複製できます。
    • 関数に割り当てられている属性の名前がわかっている場合は、それをコピーできます。しかし、モデルが新しいか不明な場合、私はその情報を持っていません。
  • 属性が別のバックボーンモデルである場合は、その属性に対して再帰的にディープコピーアルゴリズムを呼び出します。
    • 属性がネイティブバックボーンメソッドを使用するバックボーンモデルであるかどうかを確認できず、回避策を探しています。

私が現在持っているものの簡略版は以下のとおりです。

/ **
 *backbone.jsモデルのディープコピーを実行します
 *コピーのすべてのバインディングが失われます
 *@paramorgModel-コピーする元のモデル
 * /
関数deepCopyModel(orgModel)
{{   
    var dupModel = Backbone.Model.extend({});

    var orgAttributes = orgModel.toJSON();

    var keepAttr = _。keys(orgAttributes);
    //特殊なケースを削除します
    keepAttr = _。without(keepAttr、'specialCase1'、'specialCase2');
    //またはkeepAttr=_。difference(keepAttr、['specialCase1'、'specialCase2']);

    //未定義の値を削除します
    keepAttr = _。filter(keepAttr、function(key){
        return(typeof(attributes [key])!= "undefined");
    });
    //フィルタリング後に結果の属性リストを取得します
    var result = _。pick(attributes、keepAttr);
    //setを使用してコピーに属性を割り当てます
    dupModel.set(result);

    // TODO:関数のディープコピーを実装する

    // TODO:内部モデルのディープコピーを実装する

        dupModelを返します。
}

あなたが与えることができるどんな助けまたは洞察も大いにありがたいです。ありがとう!

4

2 に答える 2

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

これがあなたの便宜のためのフィドルです:http://jsfiddle.net/S6p3F/3/

このコードを実行すると、構造は同じですが、オブジェクトが異なることがわかりsomeObjますdeepCopy

ご覧のとおりthis、関数が適用されているオブジェクトに参照がバインドされているため、関数のディープコピーは必要ありません。これは、javascriptでは、関数をasと呼び出すことは、機能的に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);

そしてフィドル: http: //jsfiddle.net/S6p3F/2/

于 2012-08-03T16:37:36.693 に答える
4

アンダースコアドロップインの代わりにLo-Dashを使用している場合は、 _。cloneDeepを使用することもできます。

var newModel = new MyModel(_.cloneDeep(oldModel.toJSON());
于 2013-08-20T08:07:52.757 に答える