Backbone.js空数组属性

我遇到了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); // ... } }); 

然后我通过addWidget添加一个小部件。 当试图getWidget我得到的结果(在Chrome中)是这样的:

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

它显示了在loggingthis.attributes时widgets不是空的,但是在loggingthis.attributes.widgets时显示为空。 有谁知道这会导致什么?

编辑我已经改变了模型实例初始化方法中的小部件数组,以避免跨多个实例的引用,我开始使用骨干嵌套与没有运气。

小心信任控制台,经常有asynchronous行为,可以让你起来。

你期待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调用开始将x的当前状态转储到控制台中,但是这个x不一定与(2)中的x匹配。

在你的情况下,你这样做:

 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) 

这会让你看到两个不同版本的widgets :在(3)中接收到的新widgets和空的原件。

当你这样做:

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

你正在抓取连接到console.log调用的this.attributesthis.attributes.widgets副本,所以(3)不会干扰你的引用,并且在控制台中看到明智的结果。

这就是答案:

它显示了在loggingthis.attributes时widgets不是空的,但是在loggingthis.attributes.widgets时显示为空。 有谁知道这会导致什么?

就基本问题而言,您可能在某个地方有一个fetch调用,并且没有考虑其asynchronous行为。 该解决scheme可能绑定到"add""reset"事件。

请记住,JS中的[]只是new Array()的别名,并且由于对象是通过引用传递的,所以Session模型的每个实例都将共享相同的数组对象。 这会导致各种问题,包括数组显示为空。

要按照你想要的方式工作,你需要在构造函数中初始化你的widgets数组。 这将为每个Session对象创build一个唯一的Widget数组,并且应该缓解您的问题:

 var Session = Backbone.Model.extend({ defaults: { // ... widgets: false }, initialize: function(){ this.set('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); // ... } }); 

使用Chrome和Firefox进行testing: 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 ]