【问题标题】:Backbone.js Empty Array AttributeBackbone.js 空数组属性
【发布时间】:2017-12-16 17:14:09
【问题描述】:

我在 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 时显示为空。有谁知道这是什么原因造成的?

编辑 我已更改模型以在初始化方法中实例化小部件数组以避免跨多个实例的引用,并且我开始使用backbone-nested,但没有运气。

【问题讨论】:

  • 试试console.log(_(this.attributes).clone())console.log(_(this.attributes.widgets).clone()) 看看你会不会得到不同的结果。
  • 良好通话 - 通话时为空白 console.log(_(this.attributes).clone())
  • 从架构的角度来看,我建议您将Backbone.Collection 用于小部件数组。

标签: javascript arrays backbone.js


【解决方案1】:

要小心信任控制台,经常有异步行为可能会绊倒你。

您期望 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 不一定与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)

这会让您看到两个不同版本的 widgets:新版本在 (3) 中收到了一些东西,而原来的版本是空的。

当你这样做时:

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

您正在获取附加到 console.log 调用的 this.attributesthis.attributes.widgets 的副本,因此 (3) 不会干扰您的引用,并且您会在控制台。

这就是这个问题的答案:

记录this.attributes时显示小部件不为空,但记录this.attributes.widgets时显示为空。有谁知道这是什么原因造成的?

就根本问题而言,您可能在某处有一个fetch 调用,而您没有考虑到它的异步行为。解决方案可能是绑定到"add""reset" 事件。

【讨论】:

  • 关于tesis的精彩解释console.log()可以骗你” :)
  • 那么,如果你不能信任console.log,你如何调试你的代码?
  • @shim: console.log(_(pancakes).clone())console.log(model.toJSON()) 如果您需要获取快照而不用担心 console.log 的引用问题,则非常方便。
  • 这个答案让我很开心,让我的头发免于被拔掉。先生,我欠你一杯啤酒。
【解决方案2】:

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

要使这项工作以您想要的方式进行,您需要在构造函数中初始化您的小部件数组。这将为每个 Session 对象创建一个唯一的小部件数组,并且应该可以缓解您的问题:

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);
    // ...
    }
});

【讨论】:

  • 我可以看到这将如何成为一个问题,但是即使使用模型的单个实例,问题仍然存在。我尝试在initialize 中实例化数组,但我仍然遇到同样的问题。
【解决方案3】:

在 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
] 

【讨论】:

  • 应该更清楚 - 在尝试 getWidget 之前,我实际上在小部件数组中添加了一些内容。
  • 没有问题,只需编辑您的问题以反映所采取的所有步骤。
猜你喜欢
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 2018-10-22
  • 2019-11-15
  • 2017-05-15
  • 1970-01-01
相关资源
最近更新 更多