13

配列メンバーが空白として表示される Backbone.js モデルで奇妙な問題が発生しています。次のようになります。

var Session = Backbone.Model.extend({
    defaults: {
        // ...
        widgets: []
    },
    addWidget: function (widget) {
        var widgets = this.get("widgets");

        widgets.push(widget);
        this.trigger("change:widgets", this, widgets);
    },
    // ...
    // I have a method on the model to grabbing a member of the array
    getWidget: function (id) {
        console.log(this.attributes);
        console.log(this.attributes.widgets);

        // ...
    }
});

次に、 経由でウィジェットを追加しますaddWidgetgetWidget(Chromeで)得た結果を試すと、次のようになります。

Object
    widgets: Array[1]
        0: child
        length: 1
        __proto__: Array[0]
    __proto__: Object
[]

ロギング時にウィジェットが空ではないことを示していますが、ロギング時には空this.attributesとして表示されますthis.attributes.widgets。誰がこれを引き起こすのか知っていますか?

EDIT 複数のインスタンス間での参照を避けるために、初期化メソッドでウィジェット配列をインスタンス化するようにモデルを変更しまし

4

3 に答える 3

23

コンソールを信頼することに注意してください。つまずく可能性のある非同期動作がしばしばあります。

console.log(x)次のように動作することを期待しています。

  1. を呼び出しますconsole.log(x)
  2. xコンソールにダンプされます。
  3. 実行は、呼び出しの直後のステートメントから続行されますconsole.log(x)

しかし、実際にはそうではなく、現実は次のようになっています。

  1. を呼び出しますconsole.log(x)
  2. ブラウザは への参照を取得xし、「実際の」console.log呼び出しをキューに入れます。
  3. JavaScript の他のさまざまな部分が実行されます (または実行されません)。
  4. その後、(2)console.logからの呼び出しは、コンソールへの現在の状態のダンプに取り掛かりますが、これは必ずしも(2)のように一致するとは限りません。xxx

あなたの場合、あなたはこれをやっています:

console.log(this.attributes);
console.log(this.attributes.widgets);

したがって、 (2)には次のようなものがあります。

         attributes.widgets
             ^         ^
             |         |
console.log -+         |
console.log -----------+

そして、(3)で何かが起こっており、それが効果的に行われているthis.attributes.widgets = [...](つまり、attributes.widget参照が変更されている) ため、(4)が発生すると、次のようになります。

         attributes.widgets // the new one from (3)
             ^
             |
console.log -+
console.log -----------> widgets // the original from (1)

これにより、 の 2 つの異なるバージョンが表示されます。 (3)widgetsで何かを受け取った新しいバージョンと、空の元のバージョンです。

これを行う場合:

console.log(_(this.attributes).clone());
console.log(_(this.attributes.widgets).clone());

のコピーを取得していてthis.attributes、それが呼び出しthis.attributes.widgetsに添付されているため、 (3)は参照に干渉せず、コンソールに適切な結果が表示されます。console.log

それがこれに対する答えです:

ロギング時にウィジェットが空ではないことを示していますが、ロギングthis.attributes時に空として表示されますthis.attributes.widgets。誰がこれを引き起こすのか知っていますか?

根本的な問題に関する限り、おそらくfetchどこかで呼び出しがあり、その非同期動作を考慮していません。"add"解決策は、おそらくor"reset"イベントにバインドすることです。

于 2012-07-13T02:08:16.707 に答える
0

Chrome と Firefox のフィドルでテスト済み: http://jsfiddle.net/imsky/XBKYZ/

var s = new Session;
s.addWidget({"name":"test"});
s.getWidget()

コンソール出力:

Object
widgets: Array[1]
__proto__: Object

[
Object
name: "test"
__proto__: Object
] 
于 2012-07-12T19:43:40.030 に答える