Skip to content

Instantly share code, notes, and snippets.

@grncdr
Forked from anonymous/index.js
Created September 23, 2012 21:36
Show Gist options
  • Save grncdr/3773123 to your computer and use it in GitHub Desktop.
Save grncdr/3773123 to your computer and use it in GitHub Desktop.
Observable object properties in javascript
/**
* A quick proof-of-concept of observable objects using JS accessors
*
* Base observable objects are created with * `new Observable(names)`, where
* `names` is an array of property names that should be observable.
*
* Instances are created by calling .create(initial_data) on the resulting
* base object, and observed with their .observe(handler) method. See the bottom
* of this file for an example.
*/
Observable = function (props) {
this.__props = props
this.__observers = []
}
function installProperty (name, changes) {
var _val
Object.defineProperty(this, name, {
get: function () { return _val },
set: function (val) {
if (val === _val) return;
// store the original value
if (typeof changes[name] === 'undefined') {
changes[name] = _val;
}
_val = val;
}
})
}
Observable.prototype.observe = function (observer) {
if (this.__observers.indexOf(observer) !== -1) return
this.__observers.push(observer)
}
Observable.prototype.create = function (init_data) {
var previous = {}
var self = new this.constructor(this.__props)
for (var _ in this.__props) {
installProperty.call(self, this.__props[_], previous)
}
if (init_data) {
for (var key in init_data) {
self[key] = init_data[key]
}
}
var notifyObservers = function () {
var changes = []
for (var k in previous) {
if (self[k] !== changes[k]) {
changes.push([self, k, self[k], previous[k]])
}
delete previous[k]
}
for (var i in changes) {
for (var j in self.__observers) {
self.__observers[j].apply(null, changes[i])
}
}
process.nextTick(notifyObservers)
}
process.nextTick(notifyObservers)
return self
}
// Usage
var Person = new Observable(['name'])
var joe = Person.create({name: 'Joe'})
function observer (instance, key, newVal, oldVal) {
console.log({
isJoe: person === joe,
key: key,
oldVal: oldVal,
newVal: newVal
})
}
joe.observe(observer)
joe.name = 'Joey J'
process.nextTick(function () {
joe.name = 'observer will never see this state'
joe.name = 'Joseph'
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment