17
2011
Dojo Beginner Gotcha: Accidental Static Fields
Many developers with a background in Software Engineering are drawn to Dojo because of its ability to simulate classical type declaration and inheritance structures via dojo.declare. Specifying a ‘class’ via dojo.declare is straight-forward, but an extremely common mistake involves the accidental declaration of a ‘static field’ (i.e. a class variable) when intending to declare an instance variable. Let’s jump right into an example to demonstrate.
Mustang Sally
Let’s use dojo.declare to specify a ‘class’ for an Automobile. This Automobile will have five instance variables and zero class (static) variables. The Automobile will have two String variables for its make and model, a Number variable for its year, an Array variable for a list of options, and an Object variable to describe its engine. One might think that a sensible way to declare this type would be something like:
dojo.provide("machines.Automobile");
dojo.declare("machines.Automobile", null, {
/* summary:
* VROOOOM!
*/
make: "",
model: "",
year: null, // YYYY
options: [],
engine: {
horsepower: 0,
size: 0
}
//...
});
Some of these instance variables are declared properly, but a few aren’t. Can you guess which ones are a problem? We’ll need to create an instance of our class to try it out. But first lets add a print() function to our “Automobile” class for convenience sake:
print: function() {
// Dump the properties into the console
console.log("%s %s %s. %s. %s hp, %f L."
,this.year
,this.make
,this.model
,this.options.toString()
,this.engine.horsepower
,this.engine.size
);
}
Let’s write some code to bash this ‘class’ around a bit. Let’s create an Acura Integra with 160 horsepower and a 1.7 Liter engine. We’ll then call print on the Integra. Next, we’ll do the same for the 127 horsepower Honda Civic. Lastly, we’ll call print again on the Integra.
// Make a car
var teg = new machines.Automobile();
// Bring in the competition
var civette = new machines.Automobile();
// Set some properties on the first car
teg.year = 1992;
teg.make = "Acura";
teg.model = "Integra";
teg.options.push("Sunroof");
teg.engine.horsepower = 160;
teg.engine.size = 1.7;
teg.print();
// Set some properties on the second car
civette.year = 1998;
civette.make = "Honda";
civette.model = "Civic";
civette.options.push("Power Steering");
civette.engine.horsepower = 127;
civette.engine.size = 1.6;
civette.print();
// How's the teg doing?
console.log("\tAfter setting the properties on the Civic, let's check back in on the Acura...");
teg.print();
The output in Firebug’s console looks like this:

Hold your horses! Who swapped the Integra’s motor for the Civics’?! Problem? Indeed! Properties of the first car were overwritten by the second. Notice that the only properties that were overwritten were those that were instantiated as an array or object. So, if you guessed earlier that options and engine were the troublesome fields, you shouldn’t be reading this tutorial as you are a Dojo genius! The moral of the story is to be wary of instantiating properties as types other than the simple string, number, or boolean. Any fields declared in-line as complex objects will be treated as ‘static’ properties shared between all instances of that type.
This is How We Do It
If you would like to use a complex object as a field, hope is not lost. The proper way to do this is to set the variable to null initially, and then instantiate it in your type’s constructor function like so:
//...
make: "",
model: "",
year: null, // YYYY
options: null,
engine: null,
constructor: function() {
this.options = [];
this.engine = {
horsepower: 0,
size: 0
};
},
//...
But hey, don’t hate on statics just yet! The concept of static class properties can be very useful. In our example, let’s assume that every Automobile had a standard set of options that was identical for each (A/C, cruise control, sunroof, etc) and we wanted to create an enumeration of these options. This would be an ideal candidate for a static array. The key to effective use of dojo.declare is to avoid accidentally creating a static variable when an instance variable is intended. Another important skill is to recognize when you have made this mistake. It is very easy to make and even veteran Dojo-slingers do it. If during a debugging session, you ever encounter a scenario where the properties of one instance of a dojo.declare‘d type is trampling another’s, you should immediately think ACCIDENTAL STATIC ALERT!

Related Posts
7 Comments + Add Comment
Leave a comment
Recent Comments
- Randy Hudson on Lessons in Widgetry: Binding Property Values to DOM Nodes in Templates
- James on A Simple Dojo DataGrid Example (or so close, yet wide right…)
- Deepesh on A Simple Dojo DataGrid Example (or so close, yet wide right…)
- RS on A Simple Dojo DataGrid Example (or so close, yet wide right…)
- Dan Lee on From Springfield to Stuttgart, an Introduction to i18n with Dojo

An article by







So, why are complex objects treated differently than simple objects in dojo.declare statements?
Yup, this has bitten me and it took a bit of digging to uncover why it went wrong. Good post!
It’s worth noting that the legacy parser (that is, dojo.parser as it behaved <= 1.5 and continues to behave with dojoType in all 1.x) actually treats the value of a tag attribute differently, if the prototype member it matches is initialized to an array, versus null or an object. The former case takes the input string and splits it by comma; the latter two will simply be run through dojo.fromJson. (There are also distinct behaviors for strings, numbers, booleans, functions, dates, and URLs.)
Example illustrating this: http://jsfiddle.net/X3WBT/ – note how the prop attribute values in the div tags are slightly different but the end result in the console output is the same for all 3.
That said, it is absolutely imperative that any "non-static" array or object properties be initialized in the constructor (or some other instance method that runs before these properties are ever manipulated). This will ensure that the properties are adequately shadowed on each instance created based off of the prototype.
I had gotten in the habit of null-initializing anything that was to become an array or object on the instance as well, specifically to deter myself and others from this pitfall, but eventually realized the minute difference with the parser behavior. Of course, if you're not interested in declaratively invoking this constructor ever, or you're already set on the Dojo 1.6+ parser behavior with data-dojo-type and data-dojo-props, then it's a non-issue and you can initialize to null all you want.
@Chris: it's not so much anything to do with dojo.declare specifically, but prototypal inheritance in general. If the property exists on the prototype but is never explicitly *set* on the instance, it's still technically referring to the prototype's property value. The moment you do this in an instance method:
this.prop = [];
You're immediately "shadowing" the prototype's 'prop' value with a value on this instance itself. However, if you access this.prop on the instance without ever shadowing it, and call methods on it which manipulate it, you're technically still manipulating the "shared" object on the prototype, and thus the change is reflected across other objects inheriting that prototype.
Ah Miko – I see Dan persuaded you to write an article on his site
Nice one.
I found this a source of some confusion as well, really because dojo.declare encourages you to program like it’s Java when of course it is something totally different.
I actually consider it dangerous to list the variables in a java field style at the top of the dojo “class”. These are effectively comments, so why not just use a comment ? if you don’t ever set or use one of them, or you use a new one in the constructor but forget to declare it, everything still works, they just rot.
The same problem you describe happens with arrays as well e.g supposing I had a crappy list for some reason :
dojo.declare(“List”, null, {
list: [],
addItem: function (item) {
this.list.push(item);
}
});
What happens here is that the list array is a property of the prototype of every object created when you use new to invoke the function e.g. new List();
In the addItem function The JS engine will not find the property “list” on “this” so it looks at the prototype to see if it has one called list, which it does thanks to the Java style field listing and uses that one, reference resolved.
By initialising the array in the constructor e.g.
dojo.declare(“List”, null, {
// properties of a new List
// list (Array)
constructor: function () {
this.list = [];
},
addItem: function (item) {
this.list.push(item);
}
});
It works as expected and this.list hides this.__proto__.list. Presumably this fashion for listing the properties each instance will have is only done to make it more familiar to Java or C++ developers as there is no need to do it at all and infact it could be argued it wastes memory. e.g. if I have this :
dojo.declare(“List”, null, {
list: [],
constructor: function () {
this.list = [];
},
addItem: function (item) {
this.list.push(item);
}
});
We now have :
var foo = new List();
foo.list; // array
foo.__proto__.list // array
My advice would be to initialise all properties in the constructor, then if you want to list them at the top for readability (which is presumably why they are there) then you can add them to the top of the “class” later on, you could even just use a comment. If you actually wanted a static variable stick it on the constructor function itself e.g.
List.STATIC_VALUE = “foobar”;
or if you really meant to manipulate a property on the prototype e.g. for caching, then you could explicitly write that, e.g.
…
expensiveFunction: function () {
// assuming expensive result can be
// calculated once and will always be the same
if (!this.expensiveResult) {
// share this result with every List…
List.prototype.expensiveResult = … expenisve operation
}
}
Note that properties inherited from the prototype are read only so as soon as you use = on a property of “this” the prototype’s property with the same name is hidden.
Thanks to all of you who contribute. This site continues to impress me with the depth and quality of information. The tutorials are simple yet extremely informative, and the comments are invaluable. This really helps those of us who are now in the Dojo world and want to write good/tight code. Keep up the good work.
worth noting that your constructor should handle the case of mixing in new statics from literals, should the user choose to do so.
constructor: function(args){
args = args || {};
this.options = args.options || [];
this.engine = args.engine || { … }
}
this way when you new Thinger({ options:[1,2,3], engine:{ ftw:”!!!” } }); the actual constructor args are used, and you avoid the “static” nature of objects by ref.
Its worth reading this. Really nice. Thanks Miko Borys.