Created
August 17, 2012 16:15
-
-
Save pmuellr/3380302 to your computer and use it in GitHub Desktop.
cheap-ass kinda polly-fill for Object.observe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;(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 | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
check your debug console for results | |
<script src="observe.js"></script> | |
<script src="test.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//------------------------------------------------------------------------------ | |
// 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