为什么将儿童模型添加到两个父模型中?

时间:2015-03-08 17:41:28

标签: javascript backbone.js

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

JS Bin: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?

1 个答案:

答案 0 :(得分:5)

因为它们共享一个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;
  }
});

这是the documentation在谈到的时候所说的:

  

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

也可以使用constructor代替这一点,但我不会展示一个例子,因为我不使用Backbone并且可以轻松地显示一些误导性内容(并且文档指向使用defaults函数,所以他们可能有原因。)