Sign up ×

Here's an implementation details question for JavaScript gurus.

I have a UI with a number of fields in which the values of the fields depend in a complicated fashion on the values of seven bits of inputs. Exactly what should be displayed for any one of the possible 128 values that is changing regularly as users see more of the application?

Right now, I've for this being implemented as a decision tree through an if-then-else comb, but it's brittle under the requirements changes and sort of hard to get right.

One implementation approach I've thought about is to make an array of values from 0x0 to 0x7F and then store a closure at each location --

var tbl; // initialize it with the values
tbl[0x42] = function (){ doAThing(); doAnotherThing(); }

and then invoke them with


This, at least makes the decision logic into a bunch of assignments.

Question: is there a better way?

(Update: holy crap, how'd that line about 'ajax iphone tags' get in there? No wonder it was a little puzzling.)


So what happened? Basically I took a fourth option, although similar to the one I've checked. The logic was sufficiently complex that I finally built a Python program to generate a truth table in the server (generating Groovy code, in fact, the host is a Grails application) and move the decision logic into the server completely. Now the JavaScript side simply interprets a JSON object that contains the values for the various fields.

Eventually, this will probably go through one more iteration, and become data in a database table, indexed by the vector of bits.

The table driven part certainly came out to be the way to go; there have already been a half dozen new changes in the specific requirements for display.

share|improve this question
From what i understand of your problem, your refactoring thoughts are sound, but tbh i am not sure from your description, what it is you need :P –  Martin Jespersen Jan 12 '11 at 21:45
Does each bit determine a specific action? If so, why not perform a bitwise AND on your value against [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40] –  draeton Jan 12 '11 at 22:16
@Martin, the point is whether there is another, more flexible, way of doing this than my table of lambdas. –  Charlie Martin Jan 12 '11 at 22:34
@draeton, that's a good point. The table is actually both sparse -- many of the values are simply invalid, represent an error, but irregularly so -- and redundant, so that several values might have the same action attached, but again with no regularity. If the relationship were somewhat fixed, I could transform it to an FSA, but I tried that already and requirements changes bust the FSA. –  Charlie Martin Jan 12 '11 at 22:36
Out of curiosity, what did you decide upon? Did you find a better solution? –  Martin Jespersen Jan 21 '11 at 21:38

4 Answers 4

up vote 1 down vote accepted

Have you considered generating your decision tree on the server rather than writing it by hand? Use whatever representation is clean, easy to work with, and modify and then compile that to ugly yet efficient javascript for the client side.

A decision tree is fairly easy to represent as data and it is easy to understand and work with as a traditional tree data structure. You can store said tree in whatever form makes sense for you. Validating and modifying it as data should also be straight forward.

Then, when you need to use the decision tree, just compile/serialize it to JavaScript as a big if-the-else, switch, or hash mess. This should also be fairly straight forward and probably a lot easier than trying to maintain a switch with a couple hundred elements.

share|improve this answer

I see two options...

Common to both solutions are the following named functions:

function aThing() {}
function anotherThing() {}
function aThirdThing() {}

The switch way

function exec(bits) {
 switch(bits) {
    case 0x00: aThing(); anotherThing(); break;
    case 0x01: aThing(); anotherThing(); aThirdThing(); break;
    case 0x02: aThing(); aThirdThing(); break;
    case 0x03: anotherThing(); aThirdThing(); break;
    case 0x42: aThirdThing(); break;
    case 0x7f: ... break;
    default: throw 'There is only 128 options :P';

The map way

function exec(bits) { 
    var actions = map[bits];
    for(var i=0, action; action=actions[i]; i++)

var map = {
 0x00: [aThing, anotherThing],
 0x01: [aThing, anotherThing, aThirdThing],
 0x02: [aThing, aThirdThing],
 0x03: [anotherThing, aThirdThing],
 0x42: [aThirdThing],

in both cases you'd call

share|improve this answer
couldn't that loop be for(var action in actions) action();? –  Charlie Martin Jan 13 '11 at 2:47
It could but would make little sense. Actions in this case is an array of function references, and you don't wish to loop over arrays with for(var i in array) both because it is much slower and because it will give you uneven results across browsers. Some browsers will treat the "length" property on the array as just another member of the object and give you that as well as the function references. –  Martin Jespersen Jan 13 '11 at 8:30
[].propertyIsEnumerable('length') === false –  draeton Jan 13 '11 at 15:32

Since the situation (as you have described) is so irregular, there doesn't seem to be a better way. Although, I can suggest an improvement to your jump table. You mentioned that you have errors and duplicates. So instead of explicitly assigning them to a closure, you can assign them to named functions so that you don't have to duplicate the explicit closure.

var doAThingAndAnother = function (){ doAThing(); doAnotherThing(); }

var tbl; // initialize it with the values
tbl[0x42] = doAThingAndAnother;
tbl[0x43] = doAThingAndAnother;

Not that much of an improvement, but it's the only thing I could think of! You seem to have covered most of the other issues. Since it looks like the requirements change so much, I think you might have to forgo elegance and have a design that is not as elegant, but is still easy to change.

share|improve this answer

I've got a rough example of a JavaScript decision tree tool if you want to take a look:

share|improve this answer

Your Answer


