JavaScript: Databinding with Object.observe

This entry was posted by Rick Waldron (@rwaldron) on August 24, 2012 in JavaScript, TC39, ECMA, ECMAScript and Feature.

Everything you think you know about data binding — and every trick MVC libraries are using to pull it off — is about to be flipped on its head.

At the last ECMA/TC39 Face to Face, Rafael Weinstein presented the latest revision of the Object.observe spec, a work in progress that he and several other members of TC39 are currently authoring. Object.observe is under discussion in TC39 and will hopefully be in a future edition of the ECMAScript 262 standard. To test drive it today, grab this special build of Chromium.

The proposed behaviour of Object.observe is to provide a mechanism to observe and notify programs of mutations to specified JavaScript objects.

  1. Notify when any property is added.
  2. Notify when the value of a data property is updated
  3. Notify when any property is deleted.
  4. Notify when any property is reconfigured (aspects of a property descriptor are modified, eg. by Object.freeze)

Note: by default, get/set accessors won’t notify, but you can create custom notifiers, which I will show you below.

Object.observe will grant observability only for objects that are explicitly specified in a program—like this:

While that example shines with simplicity, there is more! We can also retrieve a notifier object, with Object.getNotifier and call its notify() method with a change record; this allows you to create your own accessor notifiers—take a look:

Changes are delivered asynchronously, at the end of every “turn”. Notice the the last value in the change set is the present value…

Notice only one “Observed…” was logged in the last example? Same turn changes are delivered together, “sometime in the future” (for explanation of how this model works, take a look at the DOM Mutation Observer spec ):

In the output, you’ll see that the “present value” is the value that we expect it to be when the [...].forEach(...) call is complete–that’s the end of the turn.

When the program requires earlier delivery or any sort of immediate control over delivery, Object.deliverChangeRecords(callback) will force an immediate delivery if there are pending changeRecords:

Data Binding in Web Applications

The rationale behind Object.observe is to provide a native, highly optimized implementation on which data binding strategies can be built. Modern web applications are generally built using one of these—primarily for some degree of data-binding, along with additional goodies to simplify the workload. Object.observe is not a drop in replacement by any means, however it does spell the end for atrocious workarounds that include property polling and DOM event “hook-binding” (latching onto every key event fired on a document is insane). In a not-too-distant future, data-binding libs will built on top of smart, asynchronous, natively optimized object observation patterns with Object.observe at the core.

Uncle JS Wants You

If you’re the author of a data-binding library, I’d like to take this opportunity to challenge you to re-write your code base using Object.observe as the core of your data observation strategy. The idea is to maintain your current API, but drop whatever mechanism you’re currently using and replace it with one built on top of Object.observe. Post links to your repo branches in the comments.

A special build of Chromium that has a prototype implementation of Object.observe is available develop your code and run tests against.

In the meantime, I’ve put together an example data-binding API called Fact that you can use as a guide for getting started on your own re-writes. All of the feedback you provide will be used by ECMA/TC39 to guide the development of the spec.

Special thanks to Rafael Weinstein, Rebecca Murphey, Mike Pennisi and Irene Ros for reviewing this blog post.

[0] ECMA/TC39 [1] Face to Face [2] Rafael Weinstein [3] Object.observe spec [4] ES5.1 [5] ECMAScript 262, 5.1 [6] TODO MVC [7] Fact [8] Chromium

This entry was posted by Rick Waldron (@rwaldron) on August 24, 2012 in JavaScript, TC39, ECMA, ECMAScript and Feature.