Observer Implementation – using defineProperties

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');

Leave a Reply

Your email address will not be published. Required fields are marked *