在Backbone.js中覆盖Model.get(attr)的最佳方法是什么?

时间:2011-07-14 15:10:27

标签: javascript 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);
    }
  }
});

我认为这并不可怕,但似乎应该有更好的方法。

3 个答案:

答案 0 :(得分:52)

这会更简单吗?

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

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

这样您也可以使用函数覆盖现有属性。你觉得怎么样?

答案 1 :(得分:2)

我认为属性是模型用来为提出问题的来电者提供答案的原材料。我实际上不喜欢让调用者对内部属性结构了解太多。它是一个实现细节。如果这种结构改变了怎么办?

所以我的答案是:不要这样做。

创建一个方法,并隐藏实现细节。它的代码更清晰,并且可以在实施过程中发挥作用。

答案 2 :(得分:1)

Model.get使用的实际属性存储在attribute属性中。你可以这样做:

// 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()呢?并且setter更复杂,因为它确认,更改通知等...现在我很抱歉我发布了这个:)