Javascript 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

我在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中)是:

当记录
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
    调用排队等待稍后
  • JavaScript的各种其他部分运行(或不运行)
  • 稍后,来自(2)
    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获取快照而不必担心引用问题,则使用
    非常方便。
    这个答案让我大开眼界,避免了头发被拔出。先生,我欠你一杯啤酒。