Javascript 主干继承模式,具有继承同一父类的类的sibings实例

Javascript 主干继承模式,具有继承同一父类的类的sibings实例,javascript,class,inheritance,backbone.js,Javascript,Class,Inheritance,Backbone.js,我遇到了一些奇怪的事情: 一个公共父类的所有子类似乎与其兄弟类一起获得“引用”属性 检查这个简单的测试用例: var MyParentClass = Backbone.View.extend({ items:['foo'], initialize: function() { } }); var MyFirstChildrenClass = MyParentClass.exte

我遇到了一些奇怪的事情:

一个公共父类的所有子类似乎与其兄弟类一起获得“引用”属性

检查这个简单的测试用例:

        var MyParentClass = Backbone.View.extend({
            items:['foo'],
            initialize: function() {
            }
        });

        var MyFirstChildrenClass = MyParentClass.extend({
            initialize: function() {
                MyFirstChildrenClass.__super__.initialize.apply(this, arguments);
                console.warn('MyFirstChildrenClass::initalize()');
                this.items.push('bar');
            }
        });

        var MySecondChildrenClass = MyParentClass.extend({
            initialize: function() {
                MySecondChildrenClass.__super__.initialize.apply(this, arguments);
                console.warn('MySecondChildrenClass::initalize()');
                console.warn(this.items); // expecting [foo] & getting [foo,bar] !
            }
        });


    var firstInstance = new MyFirstChildrenClass();
    var secondInstance = new MySecondChildrenClass();

这是由JavaScript中对象文本的计算引起的。这一行:

items:['foo'],

立即计算数组,并且父类型/子类型都包含对同一对象的引用

所有主干对象都使用对象文本进行扩展,以创建新类型。对象文本是键:值对,其中键始终是文本键,JavaScript解析器一到达该行就计算该值。因此,您将在父类中获得对数组
['foo']
的单个引用。对象在JavaScript中是通过引用的,并且每个子类将包含对同一数组的引用

解决此问题的最简单方法是将
分配给返回数组的函数(在您的情况下,这似乎不是一个好选项),或者在父类的构造函数中分配数组(如果需要,也可以分配initialize方法):


有关对象文本和值的详细讨论(在jQuery的上下文中,但这里也适用相同的原则),请参阅我的博客文章:

项目
,当您将其添加到
扩展
调用时,使新主干“类”成为类原型的一部分


由于JavaScript使用,这意味着该类的所有实例都可以使用和共享它

非常感谢你给出了这个非常清晰和有启发性的答案。我将使用this.items=\ uu.clone(this.items);在构造器中,您认为这是否合适/有效?这将非常有效。您将在每个实例中获取原始.items的副本。请记住,克隆是一个浅拷贝。如果其中一个项本身是对象引用,那么在每个子项中都会有相同的项引用。

Backbone.View.extend({
  constructor: function(){
    Backbone.View.prototype.constructor.apply(this, arguments);

    this.items = ['foo'];
  }
});