Почему мои модели javascript Backbone.js используют один и тот же «экземпляр» своего родительского класса? - PullRequest
1 голос
/ 26 мая 2011

РЕДАКТИРОВАТЬ: Исправлен мой пример, чтобы продемонстрировать поведение.

Я хотел, чтобы свойство details класса AbstractParent было тем, что я бы назвал «свойством экземпляра», но оно действовало больше как «статическое свойство». Я понимаю, что эти термины не подходят для 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 является массивом. Если это строка или объект, то она не является общей для ch1 и ch2.

Ответы [ 3 ]

2 голосов
/ 27 мая 2011

Хорошо, я разобрался с проблемой. Код моего исходного вопроса не был точным, поэтому я прошу прощения у других респондентов (они были верны в контексте кода, который я представил).

Решение описано здесь: Члены объекта Javascript, созданные в виде массивов, становятся общими для всех экземпляров класса

По сути, тот факт, что оба экземпляра Child совместно используют в качестве своего прототипа одну и ту же функцию AbstractParent, означает, что изменение чего-либо в AbstractParent будет отражено в обоих дочерних прототипах.

Причина, по которой это проявляется только при использовании массива, заключается в том, что я инициализировал массив в прототипе, а затем просто изменил его, а не переписал в функции addDetail. Когда я использовал объекты или строки для имен свойств, а затем выполнил присваивание, this в контексте во время вызова функции принадлежит экземпляру Child, поэтому выполнение this.name = 'Billy'; в функции AbstractParent фактически присоединяет вместо экземпляра Child, а не в AbstractParent. Я думал, что каждый экземпляр Child получит свой собственный экземпляр прототипа AbstractParent, и когда я получу доступ к this.name, он не найдет его в Child и вместо этого перейдет к this.prototype.name.

В коде моего вопроса я могу это исправить, добавив функцию initialize в AbstractParent, которая создает массив деталей. Но если бы я добавил функцию initialize в Child, и я бы не вызвал в ней родительский конструктор, у меня возникла бы та же проблема, что и раньше.

1 голос
/ 27 мая 2011

Вы говорите, когда вы меняете ch1.name, это также меняет ch2.name?Я запустил ваш точный код и не получил этот результат.ch2.name по-прежнему "Имя по умолчанию".

При поиске свойства name мой браузер выбирал следующие маршруты после установки ch1.name = "Billy" ...

ch1

  • inherits.child (ваш экземпляр ch1)

    • имя: "Билли"

ch2

  • inherits.child (ваш экземпляр ch2)
    • __ proto__ (ваш прототип SecondChild)
      • __ proto__ (ваш прототип AbstractParent)
        • name: «Имя по умолчанию»

Откройте консоль отладки, либо Firebug в Firefoxили Инструменты разработчика / Консоль Javascript в Chrome.

1 голос
/ 27 мая 2011

Вы назначили свойство name (или объект) для base, AbstractParent, и вы определили два объекта, которые выходят из этой базы. Таким образом, каждый независимо имеет этот объект имени, хотя они по умолчанию имеют значение, назначенное в базе.

В вашем коде, хотя вы назначили ch1.name для 'Billy', вы ничего не сделали, чтобы изменить значение name для ch2. Я утверждаю, что ваш пример кода на самом деле неверен. Значение, отображаемое в предупреждении, должно быть «Имя по умолчанию».

Не могли бы вы загрузить backbone.js в браузер, затем перейти к консоли отладчика и снова ввести приведенные выше операторы? Если вы это сделаете, я думаю, вы найдете поведение, которое вы ожидаете.

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