我遇到了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
[]
它显示在记录this.attributes
时窗口小部件不为空,但在记录this.attributes.widgets
时显示为空。有谁知道会导致什么?
修改 我已经更改了模型以在初始化方法中实例化widgets数组,以避免跨多个实例的引用,并且我开始使用backbone-nested而没有运气。
答案 0 :(得分:22)
小心信任控制台,通常会出现异步行为,可能会让你失望。
您希望console.log(x)
的行为如下:
console.log(x)
。x
被转储到控制台。console.log(x)
来电后立即继续执行该声明。但事实并非如此,现实更像是这样:
console.log(x)
。x
的引用,并将“真正的”console.log
电话排队等待以后。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),而原始版本为空。
执行此操作时:
console.log(_(this.attributes).clone());
console.log(_(this.attributes.widgets).clone());
您抓取this.attributes
和this.attributes.widgets
附加到console.log
来电的副本,因此(3)不会干扰您的参考资料你在控制台中看到了明智的结果。
这就是答案:
它显示在记录
this.attributes
时窗口小部件不为空,但在记录this.attributes.widgets
时显示为空。有谁知道会导致什么?
就潜在问题而言,您可能在某处进行了fetch
调用,并且您没有考虑其异步行为。解决方案可能是绑定到"add"
或"reset"
事件。
答案 1 :(得分:1)
请记住,JS中的[]
只是new Array()
的别名,并且由于对象是通过引用传递的,因此Session模型的每个实例都将共享同一个数组对象。这会导致各种问题,包括阵列似乎是空的。
要以您想要的方式工作,您需要在构造函数中初始化您的窗口小部件数组。这将为每个Session对象创建一个唯一的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);
// ...
}
});
答案 2 :(得分: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
]