在 javascript 中,获取或设置一个属性时进行某些处理的唯一方法是使用对象.defineProperty https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty:
Object.defineProperty(person, "b", {
get : function() {
return person.firstName + ' ' + person.surname;
},
set : function(newValue) {
var names = newValue.split(' ');
person.firsname = names[0];
person.surname = names[1];
},
enumerable : true,
configurable : true
});
但这有一些缺点:
- 不是跨浏览器
- 没有约束力,换句话说,如果
firstname
or surname
变化,从属财产fullname
没有改变。
- Calling
person.name
when person
未定义,抛出错误
- 不可能触发观察者,没有额外的代码并且了解依赖关系层次结构:
firstname
取决于fullname
,并且它可以依赖于其他属性啊啊啊!
因此Ember有了“财产”的概念,称为计算属性 http://emberjs.com/guides/object-model/computed-properties/.
它可以通过两种方式声明:
foo: Ember.computed(function({
...
}).property(dependent keys);
或使用时(默认)Ember.ENV.EXTEND_PROTOTYPES = true
:
foo: function() {
...
}.property(dependent keys);
The property(dependent keys)
, 是必需的,因为它告诉 ember 什么是属性,当更改时,将使属性更新。
fullname: function(key, value) {
// setter
if (value !== undefined) {
var names = value.split(' ');
this.set('firstname', names[0]);
this.set('surname', names[1]);
}
// always return the complete result, so nexts calls to this.get('fullname') will return the cached value
return this.get('firstname') + ' ' + this.get('surname');
}.property('firstname', 'surname')
使用此功能,您可以获得以下优势:
- 当改变时
firstname
or surname
到一个新的值,fullname
被改变了。
- The
beforeObserves
在更改值之前触发,并且observes
值改变后触发。
- 任何引用某些属性的模板都会更新
- 多次调用 person.get('firstname') 将返回缓存的值,从而节省处理。您可以使用禁用此功能
.property(..).volatile()
- 访问 null 对象时,避免 null 或未定义的错误,例如:
controller.get('person.dog.name')
回报undefined
,如果人或狗未定义。
我希望它有帮助