Skip to content

Instantly share code, notes, and snippets.

@pmuellr
Created August 17, 2012 16:15
Show Gist options
  • Save pmuellr/3380302 to your computer and use it in GitHub Desktop.
Save pmuellr/3380302 to your computer and use it in GitHub Desktop.
cheap-ass kinda polly-fill for Object.observe
;(function(){
//------------------------------------------------------------------------------
if (typeof(Object.observe) == "function") {
console.log("object.observe() is already available")
return
}
//------------------------------------------------------------------------------
// observe property changes on an object
//------------------------------------------------------------------------------
var keyObservers = "__Oo_observers"
var keyPropVals = "__Oo_propVals"
//------------------------------------------------------------------------------
Object.observe = function(object, observer) {
// check observe-able-ness
var type = typeof(object)
if (type != "object" && type != "function") {
console.log("Object.observe: trying to object an unobservable object: " + object)
return
}
// null
if (!object) return
// object already observable? add the observer
if (object[keyObservers]) {
object[keyObservers].push(observer)
return
}
// object not yet observable, make it so
Object.defineProperty(object, keyObservers, {value: []})
Object.defineProperty(object, keyPropVals, {value: {}})
object[keyObservers].push(observer)
// iterate through the properties
getProperties(object).forEach(function(property) {
// if the property is a setter, wrap the setter function
if (property.set) {
installSetterWrapper(object, property, observer)
}
// if the property is not a getter, install a getter/setter
else if (!property.get) {
installValueWrapper(object, property, observer)
}
})
}
//------------------------------------------------------------------------------
Object.unobserve = function(object, observer) {
if (!object) return
if (!observer) return
if (!object[keyObservers]) return
var observers = object[keyObservers]
var i = observers.indexOf(observer)
if (i == -1) return
observers.splice(i,1)
}
//------------------------------------------------------------------------------
function installValueWrapper(object, property, observer) {
if (!property.configurable) return
if (!property.writable) return
var descr = {
enumerable: property.enumerable,
configurable: true
}
object[keyPropVals][property.name] = property.value
descr.get = getObservablePropertyValue(object, property.name)
descr.set = setObservablePropertyValue(object, property.name)
delete object[property.name]
Object.defineProperty(object, property.name, descr)
}
//------------------------------------------------------------------------------
function getObservablePropertyValue(object, name) {
return function() {
return object[keyPropVals][name]
}
}
//------------------------------------------------------------------------------
function setObservablePropertyValue(object, name) {
return function(newValue) {
var oldValue = object[keyPropVals][name]
object[keyPropVals][name] = newValue
object[keyObservers].forEach(function(observer) {
try {
var record = {
type: "updated",
object: object,
name: name,
oldValue: oldValue
}
observer.call(null, record)
}
catch (e) {
}
})
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
function installSetterWrapper(object, property, observer) {
// TBD
}
//------------------------------------------------------------------------------
function getProperties(object) {
var result = Object.getOwnPropertyNames(object)
result = result.filter(function(propName) {
if (propName == keyObservers) return false
if (propName == keyPropVals) return false
return true
})
result = result.map(function(propName) {
var descr = Object.getOwnPropertyDescriptor(object, propName)
descr.name = propName
return descr
})
return result
}
})();
check your debug console for results
<script src="observe.js"></script>
<script src="test.js"></script>
//------------------------------------------------------------------------------
// from: http://wiki.ecmascript.org/doku.php?id=strawman:observe
// date: 2012-08-17
//------------------------------------------------------------------------------
// and then altered, marked by "pjm"
//------------------------------------------------------------------------------
function observer(records) {
console.log(records);
}
// Tests
var o = {};
var o2 = {}
o.x = undefined //pjm
o.y = undefined //pjm
o.toString = function(){return "o"} //pjm
Object.observe(o, observer);
o.x = 1;
o2.x = 2; // doesn't notify
o.x = 3;
o.y = 4;
var tmp = 5;
Object.defineProperty(o, "x", { get: function () { return tmp; }, set: function (v) { tmp = v; } });
o.x = 6; // Doesn't notify
o.toString = 7;
delete o.x;
Object.unobserve(o, observer);
o.y = 8; // Doesn't notify
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment