Подтвердить что ты не робот

Какой лучший способ переопределить Model.get(attr) в Backbone.js?

Я использую Backbone.js в первый раз, и мне это нравится. В настоящее время я не могу разобраться в динамических атрибутах моделей. Например, скажем, у меня есть модель Person, и я хочу получить полное имя:

var Person = Backbone.Model.extend({
  getFullName: function () {
    return this.get('firstName') + ' ' + this.get('surname');
  }
});

Тогда я мог бы сделать person.getFullName(). Но я хотел бы сохранить его в соответствии с другими геттерами, более похожими на person.get('fullName'). Я не вижу, как это сделать без беспорядочно переопределения Person # get. Или это мой единственный вариант?

Это то, что у меня есть до сих пор для переопределяющего варианта:

var Person = Backbone.Model.extend({
  get: function (attr) {
    switch (attr) {
    case 'fullName':
      return this.get('firstName') + ' ' + this.get('surname');
      break;
    case 'somethingElse':
      return this.doSomethingClever();
      break;
    default:
      return Backbone.Model.prototype.get.call(this, attr);
    }
  }
});

Я полагаю, это не страшно, но кажется, что должен быть лучший способ.

4b9b3361

Ответ 1

Было бы проще?

var Person = Backbone.Model.extend({
  get: function (attr) {
    if (typeof this[attr] == 'function')
    {
      return this[attr]();
    }

    return Backbone.Model.prototype.get.call(this, attr);
  }
});

Таким образом, вы также можете переопределить существующие атрибуты с помощью функций. Как вы думаете?

Ответ 2

Я бы подумал об атрибутах в качестве сырья, используемого моделью, чтобы дать ответы на звонящие, задающие вопросы. Мне на самом деле не нравится, когда звонящие слишком много знают о структуре внутренних атрибутов. Его деталь реализации. Что делать, если эта структура изменяется?

Итак, я бы ответил: не делайте этого.

Создайте метод, как вы это сделали, и скройте детали реализации. Его гораздо более чистый код и сохраняет изменения в реализации.

Ответ 3

Фактические свойства, используемые Model.get, сохраняются в свойстве атрибута. Вы можете сделать что-то вроде этого:

// function to cross-browser add a property to an object
function addProperty(object, label, getter, setter) {
    if (object.defineProperty){
      object.defineProperty(object, label, {getter: getter, setter: setter})
    }
    else {
        object.__defineGetter__(label, getter)
        object.__defineSetter__(label, setter)
    }
}

// inside the initializer of your model, add a property to the attribute object
var Person = Backbone.Model.extend({
    initialize: function(attr, options) {
        var t = this;
        ...
        addProperty(this.attributes, 'fullName',
            function() {return t.get('firstName') + ' ' + t.get('surname'),     
            function(val) {...}
        )
    }  
})

Это позволит вам выполнить person.get('fullName') по вашему желанию.

Изменить: Чтобы быть ясным, я согласен с Биллом ниже. На самом деле не стоит мириться с внутренней реализацией backbone.js. Тем более, что это неполно... как насчет escape() вместо get()? И сеттер более сложный, так как он делает валидацию, меняет уведомление и т.д. Теперь мне жаль, что я разместил это:)