A Primer on Javascript Objects – JSON vs. Functions
Modularity is one of the fundamental principles of good programming, and it’s something that is too-often overlooked in Javascript. The problem is twofold – one part is that most people approach writing Javascript without a plan, and one part is that many people don’t know that there are better ways of doing things.
Advantages of Objects
The advantages of using objects are fairly numerous, but there are two that stand out. The first is that your set of functions is probably not the only one around that uses function names like “init.” The object notation makes this a non-issue, since each object defines a namespace. Another advantage is that you don’t have global variables floating around, for much the same reason.
The second advantage is a logical one; in some cases, it makes more sense to have objects doing the work, and it’s certainly easier for somebody reading your code to figure out what “randomQuoteGenerator.init()” does, as opposed to just “init()”. In the following example, you’ll see some of this.
A Contrived Demonstration
I’m going to demonstrate two different ways of creating Javascript “objects.” One is based on JSON, the JavaScript Object Notation, and the other based on Javascript’s first-class functions. As a demonstration, we’ll write an object representing a div that shows random quotes. The object we will be creating will be defined as follows:
- A class variable called _target, which is a reference to a target <div> on the page
- A method called “update,” which updates the div with a random quote
- A method called “showAll,” which updates the div to show all the quotes.
- A method called “init,” which initializes the class variable to the target div.
A demonstration can be found here.
Functions as Objects
The functional method goes as such:
var object2def = function(){ this._target = null; this.init = function(id){ this._target = document.getElementById(id); } this.update = function(){ index = Math.floor(Math.random()*quotes.length); this._target.innerHTML = quotes[index]; } this.showAll = function(){ quotestr = ""; for(i=0;i<quotes.length;i++){ quotestr += "<p>"+quotes[i]+"</p>"; } this._target.innerHTML = quotestr; } } var object2 = new object2def;
If you were comparing this to the regular, procedural method, the first thing you would notice is the addition of “this.” Variables declared with “this” are only accessible as properties of their parent entity – in this case, the object2def class/function/variable (in Javascript, it’s all 3). The rest of it is pretty straightforward: read from a predefined list of quotes, and output what was specified above.
Notice that at the very end I make a new instance of the object. This isn’t strictly necessary, it’s just done to demonstrate the ability to create new objects. You could put 20 quote generators on the page and create randomQuoteMachines 1 through 20, and have them each control a different id. Also note that I could dispense with the init function and put the id variable call in the outer function, thereby creating a constructor of sorts. Then I could just say “var object2 = new object2def(’bar’)” to make an object that updates the div “bar”.
JSON Method
The JSON method goes like this:
var object1 = { _target : null, init : function(id){ this._target = document.getElementById(id); }, update : function(){ // An integer between 0 and the length of quotes - 1 index = Math.floor(Math.random()*quotes.length); this._target.innerHTML = quotes[index]; }, showAll : function(){ quotestr = ""; for(i=0; i < quotes.length; i++){ quotestr += "<p>"+quotes[i]+"</p>"; } this._target.innerHTML = quotestr; } }
This functions in exactly the same way as the other one. However, creating instances of it is an entirely different story, in that you can’t really; at least not without using something like Classy JSON.
A few gotchas to note about the JSON version are the commas after function declarations (except that last one), and the use of colons between name-value pairs. However, I think you’ll agree that, overall, the JSON version is somewhat cleaner, if less flexible.
If I’m creating something I know will only be used in one context, I tend to lean towards JSON, because I do like the cleanliness. However, if I’m creating something which I want to function more like an object and less like just a namespace, I’ll switch to the other method. It’s up to you which one you use, but I do recommend using something like this, as opposed to having function init(){} floating around gumming up the works.