为什么将子模型添加到两个父模型

Why are children models added to both parent models?

本文关键字:模型 两个 添加 为什么      更新时间:2023-09-26

我在下面有一个示例,它创建两个父模型,然后使用自定义函数将子模型推送到父模型数组中。

JS斌:http://jsbin.com/hamuro/4/edit?html,console

var Child = Backbone.Model.extend({});
var Parent = Backbone.Model.extend({
    defaults: {
        children: []
    },
    addChild: function() {
      var child = new Child();
      this.get('children').push(child);
      return child;
    }
  });
  var parent1 = new Parent();
  var parent2 = new Parent();
  parent2.addChild();
  parent2.addChild();
  console.log('Parent 1 Total Children: ' + parent1.get('children').length);
  console.log('Parent 2 Total Children: ' + parent2.get('children').length);

预期输出:

"家长 1 孩子总数: 0"

"家长 2 孩子总数: 2"

实际输出:

"家长 1 孩子总数: 2"

"家长 2 孩子总数: 2"

问题:

为什么即使我只指定了将子项推送到 parent2,也会将子项推送到两个父模型?

因为它们共享一个children数组: 设置默认值时,它们由赋值设置,分配的是对数组的引用,而不是数组的副本。 例如,出于与下面的ab引用同一数组相同的原因:

var a = [];
var b = a;

。只是不太直接地通过defaults机制。

相反,您可以指定一个 defaults 函数,每次都会调用该函数以创建不同的数组:

defaults功能:

var Parent = Backbone.Model.extend({
  defaults: function() [
    return {
      children: []
    };
  },
  addChild: function() {
    var child = new Child();
    this.get('children').push(child);
    return child;
  }
});

这就是文档在说时所谈论的内容:

请记住,在 JavaScript 中,对象是通过引用传递的,因此如果您将对象作为默认值包含在内,它将在所有实例之间共享。相反,defaults定义为函数。

也可以使用 constructor 来代替,但我不会展示一个示例,因为我不使用 Backbone 并且很容易显示一些误导性的东西(文档指向使用 defaults 函数,所以他们可能有原因)。