Testing Object.defineProperties using the Observer pattern. MDN shows that defaults for configurable, enumerable and writable are false. The implementation below is explicitly setting those values to false as a reminder.
function MakeObservable(obj) {
obj = obj || this;
//obj._observers = [];
Object.defineProperties (obj, {
_observers: {
value: [],
configurable: false,
enumerable: false,
writable : false
},
_watch: {
value: function (name, observer, func) {
if (!obj._observers.hasOwnProperty(name)) {
obj._observers[name] = ({observer:observer, func:func});
} else {
console.log('This property already exists on this object');
}
},
configurable: false,
writable : false
},
_unwatch: {
value: function (observer) {
var idx = obj._observers.indexOf(observer);
if (idx > -1) {
obj.slice(idx, 1);
}
},
configurable: false,
writable : false
},
_updateWatcher: {
value: function (observer) {
console.log("Generic Notification from Watched Object\n - Cannot Customize");
},
configurable: false,
writable : false
},
_updateWatchers: {
value: function (prop, value) {
var len = obj._observers.length;
for (var prop in obj._observers) {
// INTERNAL OBJECT NOTIFICATION
//obj._updateWatcher(obj._observers[watcher]);
// GET WATCHER
var watcher = obj._observers[prop];
// CALL WATCHERS CUSTOM METHOD
watcher.func(prop, value);
};
},
},
set: {
value: function(prop, value) {
obj[prop] = value;
obj._updateWatchers(prop, value);
}
},
get: {
value: function(prop) {
return obj[prop];
}
}
});
obj.set = function(prop, value) {
obj[prop] = value;
obj._updateWatchers(prop);
};
obj.get = function(prop) {
return obj[prop];
};
return obj;
}
var obj = new MakeObservable();
// CREATE WATCHER
var watcher = {
func: function(prop, value) {
console.log("FIRST WATCHER", prop, value);
}
};
// ADD WATCHER NAME, WATCHER AND FUNCTION TO BE CALLED ON UPDATE
obj._watch("watcher", watcher, watcher.func);
// TEST WATCHERS
obj.set('name', 'First Name');
// CREATE WATCHER
var watcher2 = {
func: function(prop, value) {
console.log("SECOND WATCHER", prop, value);
}
};
// ADD SECOND WATCHER NAME, WATCHER AND FUNCTION TO BE CALLED ON UPDATE
obj._watch("watcher2", watcher2, watcher2.func);
// TEST WATCHERS
obj.set('name', 'Second Name');