Шаблон наследования магистрали с экземплярами класса sibings, наследующими одного и того же родителя - PullRequest
2 голосов
/ 19 марта 2012

Я столкнулся с чем-то странным в Backbone:

Кажется, что все дочерние классы общего родительского класса получают свойства "ссылочные" со своими братьями и сестрами ... !!

Проверьте этот простой контрольный пример:

        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();

Ответы [ 2 ]

8 голосов
/ 19 марта 2012

Это вызвано оценкой литералов объекта в JavaScript. Эта строка:

items:['foo'],

вычисляет массив немедленно, и все родительские типы / подтипы содержат ссылку на один и тот же объект.

Все объекты Backbone расширены литералом объекта, чтобы создать новый тип. Объектные литералы являются парами ключ: значение, где ключ всегда является буквальным ключом, и значение оценивается, как только синтаксический анализатор JavaScript достигает этой строки. Из-за этого вы получаете единственную ссылку на массив ['foo'] в родительском классе. Объекты являются ссылками в JavaScript, и каждый из ваших подклассов будет содержать ссылку на один и тот же массив.

Самый простой способ исправить это - назначить items для функции, которая возвращает массив (что не кажется хорошим вариантом в вашем случае), или назначить массив в конструкторе родительского класса (или метод инициализации, если хотите):


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

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

Подробное обсуждение литералов и значений объектов (в контексте jQuery, но здесь применяются те же принципы) см. В моем блоге здесь: http://lostechies.com/derickbailey/2011/11/09/backbone-js-object-literals-views-events-jquery-and-el/

0 голосов
/ 19 марта 2012

items при добавлении его в вызов extend при создании нового магистрального "класса" становится частью прототипа класса.

Поскольку JavaScript использует Прототипное наследование , это означает, что оно доступно и совместно используется всеми экземплярами этого класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...