在Backbone.js中重写Model.get(attr)的最好方法是什么?

What's the best way to override Model.get(attr) in Backbone.js?

本文关键字:方法 是什么 attr js Backbone 重写 get Model      更新时间:2023-09-26

这是我第一次使用Backbone.js,到目前为止我很喜欢它。有一件事我现在还不能解决模型的动态属性。例如,假设我有一个Person模型,并且我想获得他们的全名:

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

那么我可以做person.getFullName()。但我想让它和其他getter保持一致,更像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);
    }
  }
});

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

这样会更简单吗?

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

这样你也可以用函数覆盖现有的属性。你觉得呢?

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

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

创建一个方法,并隐藏实现细节。它的代码更简洁,并且在实现更改后仍然适用。

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')。

编辑:澄清一下,我同意Bill下面的回答。不应该真的与backbone.js的内部实现打交道。特别是因为这是不完整的…用escape()代替get()怎么样?setter更复杂,因为它做验证,更改通知等。现在我很抱歉我发布了这个:)