1

编辑:修复了我的示例以演示该行为。

我希望detailsAbstractParent 的属性是我所说的“实例属性”,但它更像是“静态属性”。我意识到这些术语不适用于 javascript,那么为什么当我创建一个新的子类时它没有得到自己独特的 AbstractParent 原型?为什么他们共享同一个?

在下面的代码中,我希望得到一个空警报,但我得到的是“新详细信息”

var AbstractParent = Backbone.Model.extend({
  details: [],

  addDetail: function(detail) {
    this.details.push(detail);
  },

  getDetails: function() {
    var rtn = '';
    for(var i=0;i<this.details.length;i++) {
      rtn += this.details[i];
    }
    return rtn;
  }
});

var Child = AbstractParent.extend({});

var ch1 = new Child;
ch1.addDetail("new details");
var ch2 = new Child;

alert(ch2.getDetails()); // => 'new details'

这似乎只有在details数组时才以这种方式工作。如果它是字符串或对象,则它不被ch1and共享ch2

4

3 回答 3

2

好的,我想通了这个问题。我最初的问题代码不准确,所以我向其他响应者道歉(他们在我提供的代码的上下文中是正确的)。

此处描述了解决方案: 原型为数组的 Javascript 对象成员被所有类实例共享

基本上,两个 Child 实例作为它们的原型共享相同的 AbstractParent 函数这一事实意味着更改 AbstractParent 中的任何内容都将反映在两个孩子的原型中。

这仅在使用数组时才表现出来的原因是因为我在原型中初始化了数组,然后只是更改它而不是在addDetail函数中覆盖它。当我使用对象或字符串作为属性名称然后进行赋值this时,在函数调用时的上下文中属于 Child 实例,因此this.name = 'Billy';在 AbstractParent 函数中执行实际上是将其附加到 Child 实例,而不是在 AbstractParent 中。我在想每个 Child 实例都会有自己的 AbstractParent 原型实例,当我访问 this.name 时,它​​不会在 Child 上找到它,this.prototype.name而是会转到。

在我的问题的代码中,我可以通过向initializeAbstractParent 添加一个实例化详细信息数组的函数来解决这个问题。但是,如果我要向initializeChild 添加一个函数并且我没有调用其中的父构造函数,那么我将遇到与以前相同的问题。

于 2011-05-27T16:03:14.707 回答
1

您已经为基础 AbstractParent 分配了一个名称属性(或对象),并且您已经定义了两个从该基础扩展的对象。因此,每个都独立地拥有这个名称对象,尽管它们默认为在基中分配的值。

在您的代码中,尽管您已将 ch1.name 分配给“Billy”,但您没有做任何事情来更改 ch2 的 name 值。我认为您的代码示例实际上是错误的。警报显示的值应为“默认名称”。

您可以在浏览器中加载backbone.js,然后转到调试器控制台,然后再次输入上述语句吗?如果你这样做,我想你会找到你期望的行为。

于 2011-05-27T01:33:31.827 回答
1

你是说当你改变 ch1.name 时,它​​也会改变 ch2.name?我运行了您的确切代码,但没有得到该结果。ch2.name 仍然是“默认名称”。

在查找 name 属性时,我的浏览器在设置 ch1.name = "Billy" 后采取了以下路线...

ch1

  • inherits.child (你的 ch1 实例)

    • 名称:“比利”

ch2

  • inherits.child (你的 ch2 实例)
    • __proto__ (你的 SecondChild 原型)
      • __proto__ (你的 AbstractParent 原型)
        • 名称:“默认名称”

打开调试控制台,Firefox 中的 Firebug 或 Chrome 中的开发者工具/Javascript 控制台。

于 2011-05-27T01:43:27.833 回答