Detecting Object Mutations by Counting Properties

Have you ever included a library and wonder, "how much did this library add to the window object", or passed an object into a function and asked yourself, "did that function modify my object"? Instead of reading the source code, this article shows a quick trick for answering these questions.

How do it…

For starters we need a function to count the number of properties on an object:

function fnCountProperties(o) {
  var iCountPrototype = 0;
  var iCountOwn = 0;
  var iTotal = 0;

  for (var prop in o) {
    if (o.hasOwnProperty(prop)) {
      iCountOwn += 1;
    } else {
      iCountPrototype += 1;
    }
  }

  iTotal = new Number(iCountOwn + iCountPrototype);
  iTotal.countOwn = iCountOwn;
  iTotal.countPrototype = iCountPrototype;

  return iTotal;
}

To use, simply pass an object in before calling a function or including a library, and then pass the object in after and compare the difference:

function fnBlackBox(obj) { /* unknown */ };
var oMyObject = {
    test: 1
};
// will be 1
var iCountBefore = fnCountProperties(oMyObject);
fnBlackBox(oMyObject); // unknown operation
// if not 1, indicates that fnBlackBox modified the object
var iCountAfter = fnCountProperties(oMyObject);

Additionally, you can look at whether the property counts come from values assigned directly to the object or from the object’s prototype:

var iCount = fnCountProperties(oMyObject);
console.log('Total Count:' + iCount);
console.log('Number of direct properties:' + iCount.countOwn);
console.log('Number of prototype properties:' + iCount.countPrototype);

This breakdown is useful, because a property defined by the prototype can be modified, making it a direct property of the object. The total count will be the same, but the countOwn will increment and the countPrototype will decrement:

function Test() {};
Test.prototype = {
    state: 1
};
var oMyObject = new Test();
// iCount = 1, countOwn = 0, countPrototype = 1
var iCount = fnCountProperties(oMyObject);
oMyObject.state = 2;
// iCount = 1, countOwn = 1, countPrototype = 0
var iCount = fnCountProperties(oMyObject);

I have also created a little code pen to help illustrate:

See the Pen tIGHD by Matt Snider (@mattsnider) on CodePen.


How it works…

There is nothing fancy in the fnCountProperties function, it is using a for … in loop to iterate over the properties of an object. It then uses the hasOwnProperty method of Object to see if the property is directly assigned to the object or derived from the prototype. We create a Number instance to return the result, instead of using the primitive, so that we can assign countOwn and countPrototype to the returned value. This way developers can distinguish between whether the object or the prototype was modified.

To make this function useful, include it and run it on an object before you suspect the object is modified and compare the counts before with those after. While production ready, it is a testing tool, and you probably don’t need/want to include it in your production code. One of my favorite uses of this function is to include it early and run it before each library that I use to see how much each library modifies the window object. A well-written library won’t add more than a couple global variables.

Additionally, if you run it before including your own code, you can catch places where you did not expect the window object to be modified, and find that you forgot to include a var before defining variables.

Lastly, this technique is not full-proof, because (for performance) it doesn’t keep track of the property names. If a function removes a property and adds a new one, then the resulting counts before and after will be the same. But, since very few developers actually delete properties from objects, and since this is only meant as a developers tool, I believe this drawback is acceptable.

Using Google Play Games on the Web

As many of you know, I now work for Google on the Play Games Team. We provide APIs for game developers, implementing useful features like leaderboards and achievements, so the developer doesn't have to. While many Android developers are using our services, adoption on the web could be better, so lets take a look at how to integrate the Google Play Games Services achievements into a web game.

Getting ready

Become a Google developer ...

Site Outage Fixed - Down for 32 hours :(

I apologize that the site has been down for a couple of days. It was a perfect storm of events. For starters, Amazon told me about two weeks ago that my server was going to be terminated and that I should do something about it (they do this now and again, as they upgrade equipment). And like any good developer, I was procrastinating until the last minute (Wednesday this week). Then on Tuesday, I received ...

Event Bubble & Capture Phases

One of the less understood, but powerful feature of browser events are their phases. According to the W3C level 2 spec there are three phases[1]: AT_TARGET=2, BUBBLING_PHASE=3, and CAPTURING_PHASE=1. Most browsers also implement a fourth phase[2]: NONE=0.

Getting ready

Just a quick note that everything discussed in this article is for modern browsers (all browsers except IE <9). Prior to IE 9, Internet Explorer used its own event system, instead of conforming ...

Passing Objects into addEventListener Instead of Functions

I was reviewing the browser event stack the other day and was reminded of a rarely used feature of addEventListener that allows developers to autobind the execution context object, instead of requiring a call to bind or using a library, that is worth sharing, if you weren’t already aware.

How do it…

Typically, when attaching an event, we write:
 var myObj = { handleEvent: function (evt) { // 'this' will be scoped ...

Running Android Tests on a Device or Emulator

I have not been doing much web development lately, so its been difficult to come with interesting topics. However, I have been doing a lot of android development and since many engineers have to work cross discipline, I think an android article be relevant. This article will discuss how to run unit tests against your android code, directly on the android device or emulator.

Getting ready

You will need to install the

Cherry-Picking for Fun and Profit

In Git, it is often useful to merge one specific commit from one branch into another. Frequently this happens when Using Git Interactive Rebase With Feature Branches, as you develop in the branch, you realize that one or more of your commits should be added to master right away, but not all the CLs. Enter git cherry-pick <changelist hash> for the win! The cherry pick command allows you to merge one CL from a ...

Gaming Engine - Snake Demo v2

Last week I was busy at GDC and have not had time to put together a detailed article, so in the spirit of GDC, I thought I would share the latest iteration of my HTML5 gaming engine (still very rough). There has been a lot of progress around the Game class to support stages (or levels) and a score board to track the player’s score. The stages are demoed by a new version ...

Use && Instead of Semicolon to Separate Commands

Today’s article will be short and will cover a bash topic that frustrates me to no end. Please don’t use ; to separate commands, when you mean &&. There is an important difference between the two and many developers never realize that they want to be using && in their scripts.

How do it…

Here is a common oneliner that you might use to compile a package:
 ./configure ; make ; make ...

Using Promises to Cache Static AJAX JSON Data

This article showcases a useful caching strategy for static data that is fetch via AJAX. We will use jQuery to setup a promise and cache the data in the localStorage for subsequent page loads or data loads.

Getting ready

A modern web browser supporting localStorage and JSON. Also, a basic understanding of promises[2] is helpful.

How do it…

Here is the code:
 (function($) { var oKeyDeferredMap = {}; function fnReadData(sKey) ...