В общем пошел по пути не самому лучшему, но более стабильному. Все настройки привел к "плоскому" виду, и обернул всё это дело в прокси для отлова событий. Так и к опциям общения происходят "прямо" - Settings.value1, и к методам Settings.onSet. По хорошему это лютый говнокод, но как лучше сделать - ещё не придумал.
var Settings = new Proxy({
data: {
value1: 'some text',
value2: true,
},
/**
* Callback - on any property/value read
*
* @param {string} name
* @returns {void}
*/
onGet: function(name) {
console.log('Property "' + name + '" read action');
},
/**
* Callback - on any property/value write
*
* @param {string} name
* @param {mixed} value
* @returns {void}
*/
onSet: function(name, value) {
console.log('Property "' + name + '" write "' + value + '" action');
},
/**
* Load settings from storage
*
* @param {callable} callback
* @returns {void|object}
*/
load: function(callback) {
// Code
},
/**
* Save settings in storage
*
* @param {callable} callback
* @returns {void}
*/
save: function(callback) {
// Code
},
/**
* Remove all settings from storage
*
* @param {callable} callback
* @returns {void}
*/
clear: function(callback) {
// Code
}
}, {
/**
* Getter
*
* @param {object} target
* @param {string} name
* @returns {mixed}
*/
get: function(target, name) {
var result = undefined;
if (name in target.data) {
result = target.data[name];
}
if (name in target) {
result = target[name];
}
if (typeof target.onGet === 'function') {
target.onGet.call(target, name);
}
return result;
},
/**
* Setter
*
* @param {object} target
* @param {string} name
* @param {mixed} value
* @returns {mixed}
*/
set: function(target, name, value) {
if (name in target.data) {
target.data[name] = value;
// Save changes in storage
target.save.call(target, name, value);
}
if (name in target) {
target[name] = value;
}
if (typeof target.onSet === 'function') {
target.onSet.call(target, name, value);
}
return true;
}
});