Objects and Published Properties
enyo/CoreObject/Object
enyo/CoreObject/Object implements the Enyo framework's property publishing system. Published properties are declared in a hash called published
within a call to kind(). To get the value of a published property, call get(<propertyName>)
; to set the value, call set(<propertyName>, value)
.
By convention, the setter for a published property will trigger an optional <propertyName>Changed
method when called.
In the following example, myValue
becomes a regular property on the MyObject
prototype, with a default value of 3:
var
kind = require('enyo/kind'),
Object = require('enyo/CoreObject/Object');
var MyObject= kind({
name: 'MyObject',
kind: Object,
// declare 'published' properties
published: {
myValue: 3
},
// optional method that is called whenever set('myValue', <value>) is called
myValueChanged: function (oldValue) {
this.delta = this.myValue - oldValue;
}
});
Since we have declared a property-changed method (i.e., myValueChanged
) to observe set()
calls on the myValue
property, it will be called when set('myValue', <value>)
is called, as illustrated by the following:
myobj = new MyObject();
var x = myobj.get('myValue'); // x gets 3
myobj.set('myValue', 7); // myValue becomes 7; myValueChanged side-effect sets delta to 4
Property-changed methods are only called when setters are invoked with a different value. If you were to call set()
a second time with the same value, the changed handler would not be invoked:
myobj.set('myValue', 7); // myValue stays 7; myValueChanged is *not* called
Published properties are stored as regular properties on the object prototype, so it's possible to query or set their values directly:
var x = myobj.myValue;
Note that when you set a property's value directly, the property-changed method is not called.
Object and Array Values
In most cases, published properties should only contain basic values, such as numbers and strings. If you use an array or an object as the value of a property, the mechanism that detects changes will likely fail. This is because of the way that JavaScript handles comparisons between arrays and objects.
In JavaScript, two arrays or objects are not considered equal if they merely share the same data in the same structure; they must also be the same instance. A get(<propertyName>)
call that returns an object or array returns a reference to the internal state, since if you then modify that object or array, you modify the same instance that's held inside the kind instance.
You could work around this by overriding get()
to have it use the enyo/utils
module's clone()
method to make a shallow copy of the object or array. Then, if you pass that object into set()
, it won't be considered equal to the internal one, since it's a different object in memory. However, you would have a new problem in that the property-changed method will be called even if the two objects have all the same contents.