Experimenting with Object.observe in JavaScript

By David Voyles

Object.observe data binding browser support comparison

This article is part of a web development series from Microsoft. Thank you for supporting the partners who make SitePoint possible.

I recently built a quick prototype to get the classic interactive movie game Night Trap running in the browser. Assets stream from Azure Media Services and play through the open source video.js player as an .mp4. I also converted all of the video to adaptive streaming and am now in the process of using the Azure Media Player. Read my two-part post, Deconstructing Night Trap, for an overview of the process.

In rebuilding Night Trap, I ran into an issue where I needed to listen for an event, specifically when the URL for the video feed changes as a user is viewing a camera in a particular room. For example, I am looking at the kitchen camera and there is nothing going on, and at the 1:20 mark characters are supposed to enter the room. How do I tell the video player that the URL has changed at that time and that it should be playing the new URL I just passed in?

In comes Object.observe to save the day.

What is Object.observe?

In my search for a solution that I could use immediately, I stumbled across this excellent GitHub repo from MaxArt2501. Within it, he wrote a polyfill that allowed me to use Object.observe right now. Perfect!

His description sums up the issue well:

Object.observe is a very nice EcmaScript 7 feature that has landed on Blink-based browsers (Chrome 36+, Opera 23+) in the first part of 2014. Node.js delivers it too in version 0.11.x, and it’s supported by io.js since its first public release.
In short, it’s one of the things web developers wish they had 10-15 years ago: it notifies the application of any changes made to an object, like adding, deleting or updating a property, changing its descriptor and so on. It even supports custom events. Sweet!

The problem is that most browsers still doesn’t support Object.observe. While technically it’s impossible to perfectly replicate the feature’s behaviour, something useful can be done keeping the same API.

If you aren’t familiar with polyfills, they are basically a temporary fix, made with JavaScript, which provides a temporary solution to a feature which may / may not be implemented in the browser at some point in the future. While we’d prefer to have these features of the language built into the browser natively, we also have to understand that it’s a bit of a project to implement these things too, along with the necessity of prioritizing which features get added.

As mentioned above, this is an EcmaScript 7 feature, but we don’t even have EcmaScript 6 (JavaScript 2015) properly supported in all browsers at the moment, so I wasn’t going to hold my breath waiting for this to happen.

A fantastic polyfill

I found it extremely easy to use, and had it running in seconds. I included the Bower package, then started observing one of our objects in game which holds my URL properties, like so:


Object.observe(current,
      function (changes){
        if (changes[1]!== undefined) {
          console.log('Changes: ', changes[1].name    );
          console.log('Old Val: ', changes[1].oldValue);
        }
      }
    );

viewrawObject.observe hosted with love by GitHub

How does it work?

I had initially considered writing something on my own, where I am just polling for a changed property every few seconds, but when I came across MaxArt’s solution and saw that it worked, I stopped. Why bother running a series of tests and wasting time trying to reinvent the wheel when I had something that worked already.

Sure enough, this developer is using polling as well. Hey, as long as I don’t have performance issues, I’m fine with that.

Browser Support

I was initially concerned that I would immediately be limiting the user base, which is a common issue when adding new libraries to a project, and up until this point, I wrote all of the code myself. As long as it supports IE9+, I’m a happy camper, and sure enough, it does. Even better, it does not overwrite Chrome’s native implementation of the feature.

  • Firefox 35-39 stable and 37-41 Developer Edition
  • Internet Explorer 11
  • Microsoft Edge
  • Safari desktop 8
  • Safari iOS 8.2
  • Android browser 4.4
  • Internet Explorer 5, 7, 8, 9, 10 (as IE11 in emulation mode)
  • node.js 0.10.33-40

Wrapping It Up

As always, you can find the code for the alpha build on my GitHub account. I tend to update it a bit each day and plan on having a 5- minute demo completed by the end of September. If you’ve found some other extremely useful libraries, I’d love to hear about them as well.

Also, be sure to check out the great conversation about the pros and cons of this approach on Reddit.

More hands-on with Web Development

This article is part of the web development series from Microsoft tech evangelists on practical JavaScript learning, open source projects, and interoperability best practices including Microsoft Edge browser and the new EdgeHTML rendering engine.

We encourage you to test across browsers and devices including Microsoft Edge – the default browser for Windows 10 – with free tools on dev.modern.IE:

In-depth tech learning on Microsoft Edge and the Web Platform from our engineers and evangelists:

More free cross-platform tools & resources for the Web Platform:

  • http://aboutjws.info/ Joe Shelby

    As for the reddit discussions, there’s a lot of “missing the point”. The dirty-checking (for a polyfill version) doesn’t look at EVERY object you’ve ever created in your current session. It only has to look at those objects for whom you have added an observer. You shouldn’t need to have everything be observed if you architect it right.

    As for “slow”, the dirty check may be slow, but likely won’t be the bottleneck of your application. Again, if you do it right. The bottleneck of any modern app is the client-server communication. Unless you do something outright *stupid* on the client (involving excessive UI/DOM redraws), very little on the client makes a difference compared to that, once your application’s code is loaded…

    …and that’s another key thing about O.o() based solutions: they are MUCH smaller than the big 3 frameworks (Angular, Ember, React).

    I already made my complaint about setter-getters: your objects cease to be javascript anymore. After 5 years staring at these frameworks, I just don’t believe they are necessary. A light-weight pattern library based on O.o() or observe-js can achieve much of the same, at a fraction of the side, and make for much more readable code to an amateur javascript developer.

  • http://SalaryNet30.com willie sumrall

    l just received my second paycheck of $6395,72 workin` only few h on my Iaptop` past 5 days. My divorced’ friend with 3 kids at home, made over $10k her 1st month. It’s great makin’ this much money” when other people have to work for so much Iess. Go 2 my profiIe’ site-link to see what I do…..

    _v

  • http://aboutjws.info/ Joe Shelby

    In the end, it just doesn’t matter. O.o() has been removed from the ES7 spec and they’re asking Google to remove it from Chrome and V8. “Immutability” is all the fashion these days.

    • nielsklom

      Do you know if the same counts for Array.observe? It was kind of useful!

      • http://aboutjws.info/ Joe Shelby

        yeah, the whole spec. You could look at polymer’s observe-js (which does it by dirty-checking) or see if the polyfill that matches the original spec’s API actually handles the Array version.

        I found observe-js’s PathObserver to be the most useful, but then I have been working with Sproutcore (an Ember ancestor) and its path-based binding system for several years now.

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in Front-end, once a week, for free.