(Edit 2–3–2016: Mobservable has been rebranded to MobX)
So, ‘Object.observe’ is declared dead. And rightfully so; it’s behavior is too unpredictable. But that doesn’t mean that it is actually a bad idea to have observable objects. Actually, having observable objects is a very powerful concept. So fear not, the MobX library can observe your objects in an efficient manner! And best of all, unlike ‘Object.observe’, it runs on any ES5 environment. It’s API is quite similar to ‘Object.observe’. Seeing is believing, so let’s try it out:
That’s all! ‘observable’ decorates any object you pass into it so that MobX can observe it. From there on you can use ‘observe’ to subscribe to future changes in the object.
How does it work?
The ‘observable’ function creates setters for all properties of an object and for all indices in an array. This makes it possible to detect changes. This approach is a lot more efficient than, for example, dirty checking. Actually, changes are detected and reported synchronously. This makes observers more predictable and easier to debug. Surely, you can always add your own asynchronous layer on top of that if needed. By default new values assigned to observable structures will become observable themselves as well. This enables deep observing.
By using ‘mobx.observe’ you can once again observe changes in objects and arrays. But actually ‘observe’ is quite a low-level approach. MobX offers way more powerful concepts! MobX is a Transparent Functional Reactive Programming (TFRP) library. It creates functions that automatically re-evaluate when relevant data structures change. It analyses the data dependencies of your functions and (un)subscribes to observable data structures automatically for you. Here is an example:
As you can see, ‘autorun’ is actually a way more powerful concept than ‘observe’. It runs the given function automatically, but only when really needed. It observes deeply. It automatically subscribes to new ToDo’s. And it even unsubscribes from ToDo’s when they are no longer relevant for the function. This is a very powerful concept to keep any kind of derived data automatically and efficiently in sync with data. Things like computed values or even complete user interfaces.
So, if you need to observe complex data structures in a reliable way, just try MobX.
Applying ‘mobx.observable’ is a very powerful way to create observable structures. However, due to ES5 limitations, there are two things to be aware of:
- Adding a new property to an existing object is not detected automatically. Either declare the property upfront with an ‘undefined’ value, use ‘mobx.extendObservable’ to add the property, or create an observable ES6 like map using ‘mobx.map()’.
- Observable arrays aren’t actually arrays but objects instead. They behave just like normal arrays but external libraries might not properly recognize them. In such cases, just ‘.slice()’ the array before passing it to an external library.