Backbone.js доступ к атрибутам модели в модели - this.attribute VS this.get('attribute')?

По моему мнению, атрибуты модели Backbone.js должны быть объявлены как несколько частные переменные-члены, говоря

this.set({ attributeName: attributeValue })
// accessing the value
this.get('attributeName');

Но когда я пишу функции whitin в реальной модели, кажется гораздо проще сказать вот так:

this.attributeName = attributeValue;
// accessing the value
this.attributeName;

Также я бы предположил, что последняя версия будет быстрее обрабатываться, поскольку она не проходит через управление событиями backbone.js.

Поэтому мне было интересно, как вы относитесь к атрибутам, которые в основном используются внутри модели. Это те атрибуты, которые на самом деле хотели бы быть немного экранированными снаружи, поэтому их просмотр, как в последнем примере, может быть, не совсем прав. Когда я рассматриваю примеры для вида backbone.js, который не имеет методов get и set, кажется, что это хорошо, как во втором примере. Итак, есть ли какое-нибудь хорошее правило, когда использовать get/set (attribute) или this.attribute при кодировании в модели? Или, может быть, пример модели, которая делает это более ясным?

Ответы

Ответ 1

Когда использовать model.get(property) и model.set(...)

Вы должны использовать get и set для доступа к данным модели. Это означает любые атрибуты, которые являются частью сериализованного представления модели, которые извлекаются с помощью fetch и сохраняются с помощью save.

Когда использовать model.attributes.property

Никогда.

Вы всегда должны использовать get, и особенно set, вместо прямого доступа к объекту model.attributes, хотя я видел противоречивые мнения об этом. Я считаю, что существует контракт между model и его потребителями, который гарантирует, что потребитель может быть уведомлен о любых изменениях данных модели с помощью события change. Если вы изменяете объект внутренних атрибутов напрямую, события не отправляются, и этот контракт нарушен. Магистральные события очень быстрые, особенно если у вас нет слушателей, прикрепленных к ним, и это не точка, которая выигрывает от чрезмерной оптимизации с вашей стороны.

Хотя доступ к атрибутам напрямую вместо get является совершенно безвредным для него, его следует избегать, поэтому объект attributes можно считать полностью, полностью закрытым.

Если вам абсолютно необходимо предотвратить некоторые события запуска изменения, вы можете использовать опцию silent:true: model.set({key:val}, {silent:true}). Это нарушает вышеупомянутый контракт, и даже сама документация Backbone дает следующую оговорку:

Обратите внимание, что это редко, возможно, даже никогда, хорошая идея. Передача определенного флага в вариантах обратного вызова вашего события для просмотра и выбора игнорирования обычно будет работать лучше.

Когда использовать model.property

Любые свойства, которые не являются данными, то есть временными переменными состояния, рассчитанными свойствами и т.д., могут быть привязаны непосредственно к объекту модели. Эти свойства следует считать временными и транзитивными: их можно воссоздать при инициализации модели или в течение ее жизни, но они не должны сохраняться, будь то государственные или частные. Типичным соглашением об именах является префикс private properties с типом _ следующим образом:

this._privateProperty = 'foo';
this.publicProperty = 'bar';

Ответ 2

Никогда не является неполным ответом.

Иногда вам нужен доступ к коллекции атрибутов модели - независимо от того, какие атрибуты могут быть. Рассмотрим метод утилиты для выполнения вычислений по атрибутам, форматирование их для вывода и т.д.

Удобный способ сделать это - получить доступ к параметрам model.attributes

Рассмотрим один из вариантов ниже:

var attributesNames = ['foo', 'bar', 'baz'];
var attributes = _(attributesNames ).map(function(attr) { return model.get(attr); });

callSomeUtilityMethod(attributes);

Две проблемы:

  • Мы представили связь в коллекции "attributesNames". Что делать, если этот список изменяется?
  • Мы потеряли ассоциацию имени/значения. Мы могли бы переписать вышеприведенную карту, но она станет больше работать.

В этом случае гораздо удобнее сделать что-то вроде этого:

callSomeUtilityMethod(model.attributes);