Javascript Backbone.js空数组属性
我在Backbone.js模型中遇到了一个奇怪的问题,其中一个数组成员显示为空白。它看起来像这样:Javascript Backbone.js空数组属性,javascript,arrays,backbone.js,Javascript,Arrays,Backbone.js,我在Backbone.js模型中遇到了一个奇怪的问题,其中一个数组成员显示为空白。它看起来像这样: var Session = Backbone.Model.extend({ defaults: { // ... widgets: [] }, addWidget: function (widget) { var widgets = this.get("widgets"); widgets.push(widg
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中)是:
当记录this.attributes
时,它显示小部件不是空的,但当记录this.attributes.widgets
时,它显示为空。有人知道这是什么原因吗
编辑
我已经更改了模型,在初始化方法中实例化了widgets数组,以避免跨多个实例引用,我开始使用时运气不佳。在Chrome和Firefox中测试: 控制台输出:
Object
widgets: Array[1]
__proto__: Object
[
Object
name: "test"
__proto__: Object
]
请记住,JS中的
[]
只是新数组()
的别名,由于对象是通过引用传递的,因此会话模型的每个实例都将共享相同的数组对象。这会导致各种各样的问题,包括数组看起来是空的
要使其按您想要的方式工作,您需要在构造函数中初始化您的小部件数组。这将为每个会话对象创建一个唯一的小部件数组,并将缓解您的问题:
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);
// ...
}
});
在信任控制台时要小心,通常会有异步行为使您绊倒 您希望console.log(x)的行为如下:
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);
// ...
}
});
console.log(x)
x
被转储到控制台console.log(x)
调用之后的语句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);
// ...
}
});
console.log(x)
x
的引用,并将“real”控制台.log
调用排队等待稍后console.log
调用会将x
的当前状态转储到控制台中,但该x
不一定与x
匹配,因为它在(2)中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)
这使您看到两个不同版本的小部件
:在(3)中接收内容的新版本和空白的原始版本
执行此操作时:
console.log(_(this.attributes).clone());
console.log(_(this.attributes.widgets).clone());
您正在抓取连接到控制台的this.attributes
和this.attributes.widgets
的副本。记录调用,因此(3)不会干扰您的引用,您可以在控制台中看到合理的结果
这就是答案:
当记录this.attributes
时,它显示小部件不是空的,但当记录this.attributes.widgets
时,它显示为空。有人知道这是什么原因吗
就根本问题而言,您可能在某处有一个fetch
调用,而您没有考虑它的异步行为。解决方案可能是绑定到“添加”
或“重置”
事件。可能应该更清楚-在尝试getWidget
之前,我实际上向widgets数组添加了一些内容。没问题,只需编辑您的问题以反映所采取的所有步骤。尝试console.log(u(this.attributes.clone())
和console.log(u(this.attributes.widgets).clone())
并查看是否得到不同的结果。很好的调用-调用console.log(u(this.attributes.clone())
时它是空白的,从体系结构的角度来看,我建议您对widgets数组使用主干.Collection
。我可以看出这会成为一个问题,然而,即使只有一个模型实例,问题仍然存在。我试着在initialize
中实例化数组,但我还是遇到了同样的问题。关于TESI的精彩解释“console.log()
可以欺骗你”:)那么,如果你不信任console.log,你怎么调试你的代码呢?@shim:console.log((煎饼).clone())
或者console.log(model.toJSON())如果您需要使用console.log获取快照而不必担心引用问题,则使用
非常方便。
这个答案让我大开眼界,避免了头发被拔出。先生,我欠你一杯啤酒。