javascript 在 Backbone.js 中覆盖 Model.get(attr) 的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6695503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the best way to override Model.get(attr) in Backbone.js?
提问by Skilldrick
I'm using Backbone.js for the first time, and liking it so far. One thing I can't work out at the moment in dynamic attributes of models. For example, say I have a Person model, and I want to get their full name:
我是第一次使用 Backbone.js,到目前为止我很喜欢它。我目前无法在模型的动态属性中解决一件事。例如,假设我有一个 Person 模型,我想获取他们的全名:
var Person = Backbone.Model.extend({
getFullName: function () {
return this.get('firstName') + ' ' + this.get('surname');
}
});
Then I could do person.getFullName()
. But I'd like to keep it consistent with the other getters, more like person.get('fullName')
. I don't see how to do that without messily overriding Person#get. Or is that my only option?
那我就可以了person.getFullName()
。但我想让它与其他 getter 保持一致,更像是person.get('fullName')
. 如果不凌乱地覆盖 Person#get,我不知道如何做到这一点。或者这是我唯一的选择?
This is what I've got so far for the overriding option:
到目前为止,这是我对覆盖选项的了解:
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);
}
}
});
I suppose it's not terrible, but it seems there should be a better way.
我想这并不可怕,但似乎应该有更好的方法。
回答by bytespider
Would this be simpler?
这会更简单吗?
var Person = Backbone.Model.extend({
get: function (attr) {
if (typeof this[attr] == 'function')
{
return this[attr]();
}
return Backbone.Model.prototype.get.call(this, attr);
}
});
This way you could also override existing attributes with functions. What do you think?
通过这种方式,您还可以使用函数覆盖现有属性。你怎么认为?
回答by Bill Eisenhauer
I would think of attributes as the raw materials used by a model to provide answers to callers that ask the questions. I actually don't like having callers know too much about the internal attribute structure. Its an implementation detail. What if this structure changes?
我认为属性是模型用来为提出问题的调用者提供答案的原材料。我实际上不喜欢让调用者对内部属性结构了解太多。它是一个实现细节。如果这种结构发生变化怎么办?
So my answer would be: don't do it.
所以我的回答是:不要这样做。
Create a method as you've done and hide the implementation details. Its much cleaner code and survives implementation changes.
像您一样创建一个方法并隐藏实现细节。它的代码更简洁,并且在实现更改后仍然存在。
回答by John
The actual properties used by Model.get are stored in the attribute property. You could do something like this:
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) {...}
)
}
})
This will allow you to do person.get('fullName') as you requested.
这将允许您按照要求执行 person.get('fullName') 。
Edit: To be clear, I agree with Bill's answer below. Shouldn't really be dinking around with the internal implementation of backbone.js. Especially since this is incomplete...what about escape() instead of get()? And the setter is more complex, as it does validation, change notification, etc...now I'm sorry I posted this :)
编辑:明确地说,我同意比尔在下面的回答。真的不应该考虑backbone.js 的内部实现。尤其是因为这是不完整的……escape() 而不是 get() 呢?而且 setter 更复杂,因为它进行验证、更改通知等......现在我很抱歉我发布了这个:)